<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Jan-Philipp Litza</title>
    <description></description>
    <link>https://jplitza.de/</link>
    <atom:link href="https://jplitza.de/blog/feed/" rel="self" type="application/rss+xml"/>
    <pubDate>Wed, 29 Oct 2025 22:07:02 +0100</pubDate>
    <lastBuildDate>Wed, 29 Oct 2025 22:07:02 +0100</lastBuildDate>
    <generator>Jekyll v4.4.1</generator>
    
      
      <item>
        <title>Garagentormotor in Home Assistant einbinden</title>
        <description>&lt;p&gt;Unser Garagentor wurde bereits als wir die Garage übernahmen von einem Motor angetrieben. Um genau zu sein von einem „novoferm VivoPort“. Der hat zwar immerhin eine Fernbedienung, aber leider auch nur genau eine. Man könnte welche nachkaufen und anlernen, aber die hätte ich dann im entscheidenden Moment doch nicht dabei.&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Außer mit der Fernbedienung kann man den Motor mit einem kleinen blauen Knopf unten am Gehäuse starten. Und da dachte ich mir: Den Knopfdruck kann man doch auch simulieren! Also habe ich mir einen &lt;a href=&quot;https://www.shelly.com/de/products/shelly-1-gen3&quot;&gt;Shelly 1 Gen3&lt;/a&gt; besorgt und ein wenig gelötet: Auf der Platine des Motors selbst habe ich mir direkt am Eingang die 24V und Erde mit einem Kabel abgegriffen; außerdem beide Seiten des Schalters.&lt;/p&gt;

&lt;p&gt;Nach entsprechender Verkabelung klappt das auch wunderbar. Der Shelly hat einen Auto-OFF Timer von 0,2s eingestellt, damit er einen kurzen Knopfdruck simuliert anstatt den Knopf gedrückt zu halten. Damit konnte ich also über Home Assistant das Garagentor vom Handy aus auf- und zumachen – außer bei Regen, dann ist das WLAN aktuell zu schwach in der Garage.&lt;/p&gt;

&lt;p&gt;Aber schon am nächsten Tag habe ich versehentlich auf dem Heimweg das Garagentor geschlossen anstatt es zu öffnen, weil jemand anders es schon kurz vorher geöffnet hatte. Blöd. Also muss ich auch den aktuellen Zustand erkennen können.&lt;/p&gt;

&lt;p&gt;Jetzt gäbe es viele Möglichkeiten, zu erkennen ob das Garagentor offen ist. Da der Shelly aber so schön im Gehäuse des Motors verbaut war wollte ich auch die Zustandserkennung irgendwie dort ansiedeln. Da erschien mir eine Art Neigungssensor das einfachste zu sein, da der Motor am Tor montiert ist und sich daher mit ihm zusammen neigt. Mit genauer Winkelangabe könnte man dem Tor sogar digital beim Öffnen und Schließen zusehen, bräuchte aber zusätzliche Hardware. Mir reicht vorerst eine digitale Auf/Zu-Angabe, die ich zudem über den Schalter-Eingang des Shelly selbst realisieren könnte.&lt;/p&gt;

&lt;p&gt;Jetzt sind solche digitalen Neigungsschalter zwar Centartikel, aber nur im Fachhandel erhältlich, sodass die Versandkosten den Warenwert um ein Vielfaches übersteigen. Außerdem: Wo wäre da der Spaß?&lt;/p&gt;

&lt;p&gt;Also habe ich so einen Neigungsschalter selbst gebaut! Dazu habe ich einen alten Kugelschreiber seiner Miene beraubt und stattdessen eine Metallkugel eingesetzt. Diese rollt darin je nach Lage hin und her und verbindet am einen Ende zwei Kabelenden, die ich im Schraubverschluss eingeklemmt und vorne durch die Öffnung herausgeführt habe.&lt;/p&gt;

&lt;p&gt;Und schon habe ich einen Neigungsschalter zum Anschluss am Schalter-Eingang des Shelly. Im Foto ist zu sehen wie er rechts am Rand auch noch Platz im Gehäuse des Motors fand. In den Einstellungen des Shelly musste ich natürlich noch Eingang und Ausgang entkoppeln (auf „Detached“ stellen). Außerdem sollte man in den Einstellungen des Eingangs die Option „Enable factory reset from input“ deaktivieren&lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;figure class=&quot;image&quot;&gt;
    &lt;a href=&quot;/blog/files/2025-07-garagentor.jpg&quot;&gt;
        &lt;img src=&quot;/blog/files/2025-07-garagentor.jpg&quot; alt=&quot;Das geöffnete Gehäuse des Garagentormotors mit Shelly (blau) und Neigungsschalter (Kugelschreiber am Rechten Rand)&quot; /&gt;
    &lt;/a&gt;

    &lt;figcaption&gt;Das geöffnete Gehäuse des Garagentormotors mit Shelly (blau) und Neigungsschalter (Kugelschreiber am Rechten Rand)&lt;/figcaption&gt;

&lt;/figure&gt;

&lt;p&gt;Schließlich musste ich in Home Assistant noch Eingang und Schalter des Shelly zu einer Garagentor-Entität machen, um sie hübsch darstellen zu können:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;cover&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Garagentor&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{&quot;on&quot;:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;closed&quot;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;off&quot;:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;open&quot;}[states(&quot;binary_sensor.shelly1g3_0123456789ab_input_0_input&quot;)]&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;default(None)&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;}}&apos;&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;device_class&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;garage&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;optimistic&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;open_cover&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;&amp;amp;garagedoor_action&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;switch.turn_on&lt;/span&gt;
          &lt;span class=&quot;na&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;entity_id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;switch.shelly1g3_0123456789ab_switch_0&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;close_cover&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;*garagedoor_action&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Diese ganze Lösung ist nicht nur komplett im ursprünglichen Gehäuse versteckt, sondern auch kompatibel zur klassischen Steuerung: Sowohl die Fernbedienung als auch der Knopf funktionieren noch wie zuvor, und der Zustand in Home Assistant wird trotzdem passend aktualisiert. Dafür war sie preislich vermutlich sogar günstiger als eine Fernbedienung nachzukaufen.&lt;/p&gt;

&lt;p&gt;Jetzt bleibt (neben dem grenzwertigen WLAN-Empfang) nur noch ein Problem, das ich noch nicht gelöst habe. Während der Motor läuft fällt die Spannung so stark ab, dass der Shelly neustartet. In den bis zu 60 Sekunden nach dem Senden des Signals zum Öffnen oder Schließen (egal ob der Home Assistant oder Fernbedienung oder Knopf) ist also keine Kommunikation möglich und der Zustand wird nicht aktualisiert. Da der Neigungsschalter aber eh erst auslöst wenn das Tor fast ganz offen ist macht das beim Öffnen nur wenig Unterschied. Eventuell könnte ich mit einem passend dimensionierten&lt;sup id=&quot;fnref:3&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; Kondensator am Eingang des Shelly sowie einer Diode vom 24V-Eingang der Motor-Platine lösen, aber dazu stört es mich aktuell zu wenig.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;Wir nutzen die Garage eher mit Fahrrädern, sodass es keine Lösung ist, die Fernbedienung einfach im Auto oder beim Autoschlüssel zu lagern. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;Ask me how I know… Der Eigenbau scheint etwas zu federn und daher gerne mal ungewollt den Shelly auf Werkseinstellungen zurücksetzen. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot;&gt;
      &lt;p&gt;Ich habe mir noch nicht angelesen, wie man das eigentlich berechnet. Ob ich da auch bei &lt;a href=&quot;https://xkcd.com/3106/&quot;&gt;1 Farad&lt;/a&gt; landen würde? &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Mon, 28 Jul 2025 00:00:00 +0200</pubDate>
        <link>https://jplitza.de/blog/2025/07/28/garagentor-home-assistant.html</link>
        <guid isPermaLink="true">https://jplitza.de/blog/2025/07/28/garagentor-home-assistant.html</guid>
        
        
      </item>
      
    
      
      <item>
        <title>Document management, part 3: Scanning documents</title>
        <description>&lt;p&gt;I previously always used gscan2pdf for scanning. A great piece of software for technically minded folks, providing tweaks for every option and kind of integrating OCR. But for batch scanning, that workflow was simply too cumbersome. And OCR was automatically done in a later stage anyway, as discussed in &lt;a href=&quot;/blog/2025/07/22/document-management-1-paperless-ngx.html&quot;&gt;the first part of this post series&lt;/a&gt;. So I had a look at the alternatives.&lt;/p&gt;

&lt;p&gt;When scanning documents, most business devices have a function to send an email somewhere, with the document attached. My decades-old Epson BX635FWD, which I nowadays only use for its duplex scanning capabilities (not printing), doesn&apos;t have such a feature. Tt does have network connectivity! (Although its WiFi only supports WPA-Personal, not WPA2, making it incompatible with any WiFi network in 2025 - but it does have RJ45 as well.) But in its webinterface, you can configure almost nothing (except for &quot;AirPrint&quot; and &quot;Google Cloud Print&quot;).&lt;/p&gt;

&lt;p&gt;But it does support hosting a file share itself! Of course you need to provide it with something to share, so I plugged in a USB thumbdrive. Now, what exactly is a &quot;file share&quot;? Probably SMB/CIFS. But opening the share via either Nautilus/GVfs/Gio/whatever-it&apos;s-called-nowadays or smbclient failed with strange error messages. The latter at least was a bit descriptive:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ smbclient -L //EPSON63556D.fritz.box/
Protocol negotiation to server EPSON63556D.fritz.box (for a protocol between SMB2_02 and SMB3) failed:  NT_STATUS_INVALID_NETWORK_RESPONSE
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;So there is something there, it just doesn&apos;t do what&apos;s expected. The important bit is in parenthesis: The printer doesn&apos;t speak at least SMB2_02! &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;man smb.conf&lt;/code&gt; provides us with the option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;client min protocol&lt;/code&gt; and its possible values, of which I&apos;ll just choose the lowest:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ smbclient -L //EPSON63556D.fritz.box/MEMORYCARD --option=&apos;client min protocol=CORE&apos;
Server does not support EXTENDED_SECURITY  but &apos;client use spnego = yes&apos; and &apos;client ntlmv2 auth = yes&apos; is set
Anonymous login successful
Password for [WORKGROUP\jplitza]:

	Sharename       Type      Comment
	---------       ----      -------
	IPC$            IPC       IPC Service
	MEMORYCARD      Disk      EPSON
Reconnecting with SMB1 for workgroup listing.
Server does not support EXTENDED_SECURITY  but &apos;client use spnego = yes&apos; and &apos;client ntlmv2 auth = yes&apos; is set
Anonymous login successful

	Server               Comment
	---------            -------

	Workgroup            Master
	---------            -------
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Hm, so what should I use for login? I didn&apos;t configure any user! Also, I should probably change that option it complains about…&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;smbclient //EPSON63556D.fritz.box/MEMORYCARD --option=&apos;client min protocol=CORE&apos; --option=&apos;client use spnego=no&apos; -U WORKGROUP/user%pass -c ls
lpcfg_do_global_parameter: WARNING: The &quot;client use spnego&quot; option is deprecated
lpcfg_do_global_parameter: WARNING: The &quot;client use spnego&quot; option is deprecated
  EPSCAN                              D        0  Thu Mar  6 21:22:56 2025
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Yay! So it just accepts all credentials. Also, my ability to downgrade the connection smbclient establishes to such a low security level that my scanner supports it might come to an end sooner or later, given that option is deprecated. But for now, it works!&lt;/p&gt;

&lt;p&gt;The rest is just a little Bash scripting to fetch all documents from the scanner into the current working directory and delete them on the printer (so they don&apos;t lie around unencrypted, and also do save space on the thumbdrive).&lt;/p&gt;
&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/usr/bin/env bash&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; pipefail

&lt;span class=&quot;nv&quot;&gt;SHARE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;//EPSON63556D.fritz.box/MEMORYCARD&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;TMPFILE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;mktemp&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

cleanup&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$TMPFILE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;trap &lt;/span&gt;cleanup EXIT

smbclient&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;command &lt;/span&gt;smbclient &lt;span class=&quot;nt&quot;&gt;-d0&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-U&lt;/span&gt; WORKGROUP/user%password &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$SHARE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;client use spnego=no&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--option&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;client min protocol=CORE&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$@&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

smbclient &lt;span class=&quot;nt&quot;&gt;-Tcag&lt;/span&gt; - | &lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-vx&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--strip-components&lt;/span&gt; 3 &lt;span class=&quot;nt&quot;&gt;--backup&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;numbered &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$TMPFILE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;while &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;read &lt;/span&gt;FILENAME&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
    &lt;/span&gt;smbclient &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;del &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$FILENAME&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt; &amp;lt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$TMPFILE&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;why-no-cifs-mount&quot;&gt;Why no cifs mount&lt;/h3&gt;

&lt;p&gt;I specifically wanted a userspace solution for this problem, because the device isn&apos;t always powered on. I was able to mount it using the cifs module of the Linux kernel using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mount -t cifs //EPSON63556D.fritz.box/MEMORYCARD /mnt/scanner -o vers=1.0,sec=none&lt;/code&gt;, but that mount would make the whole system hang when the device was turned off.&lt;/p&gt;

&lt;p&gt;Also, I was positively surprised to find out how much smbclient was actually able to do! That &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--tar&lt;/code&gt;  option really made the whole task quite easy.&lt;/p&gt;

&lt;h3 id=&quot;and-in-nextcloud&quot;&gt;And in Nextcloud?&lt;/h3&gt;

&lt;p&gt;The above script successfully worked for several months, copying the documents into the &quot;consume&quot; folder of Paperless-ngx. But since I&apos;m thinking about migrating that functionality back into Nextcloud, I wanted to see if I could simply set up an&lt;a href=&quot;https://docs.nextcloud.com/server/latest/admin_manual/configuration_files/external_storage/smb.html&quot;&gt;external SMB/CIFS storage&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;My first attempt played out like this:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Me: *trying to add an external SMB storage&lt;em&gt;&lt;br /&gt;
Nextcloud: &quot;This action needs authentication&quot;&lt;br /&gt;
Me: &quot;OK, sure thing.&quot; *lets password manager fill in password&lt;/em&gt;&lt;br /&gt;
Nextcloud: &quot;Wrong password&quot;&lt;br /&gt;
Me: &quot;Err, what? No, it&apos;s definitely correct!&quot; *tries again&lt;em&gt;&lt;br /&gt;
Nextcloud: *just hangs there&lt;/em&gt;&lt;br /&gt;
Me: *opens browser devtools* &quot;Oh look, the response says &apos;Invalid storage backend &quot;smb&quot;&apos;&quot;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yeah well… turns out I hit three bugs at once:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The error message was wrong. My password wasn&apos;t wrong at all, but the password dialog interprets every non-OK response that way. After some digging, that seems to be a global problem with that dialog in the Nextcloud frontend.&lt;/li&gt;
  &lt;li&gt;The second password entry didn&apos;t even trigger a request.&lt;/li&gt;
  &lt;li&gt;The smb backend actually should be available, since the server has smbclient installed, which the aforementioned docs say is sufficient.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That last one actually was introduced only recently. You can find the details in &lt;a href=&quot;https://github.com/nextcloud/server/issues/54047&quot;&gt;the issue I filed&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So after the detour of fixing that bug, I was able to successfully attempt the setup - with the expected problems, since there is no interface to specify custom options for smbclient. So I had to insert those pesky options into the system-wide &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/samba/smb.conf&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-ini highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;[global]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# lower client security standards for Epson printer to work
&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;py&quot;&gt;spnego&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;no&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;min&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;py&quot;&gt;protocol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;CORE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now my idea was to set up a Nextcloud flow to move the files to permanent storage and start OCR. Alas… how would Nextcloud know there were new files on the share?&lt;/p&gt;

&lt;p&gt;The answer seems to be to regularly execute &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;occ files_external:scan 2&lt;/code&gt; in a cronjob or systemd timer. Not pretty, but doable.&lt;/p&gt;

&lt;p&gt;But another problem arose: How to even move a file in a flow? The number of &lt;a href=&quot;https://apps.nextcloud.com/categories/workflow&quot;&gt;apps that provide flow actions&lt;/a&gt; seems to be quite small, and they are either highly specific integrations or as broad as &quot;call a script&quot; or &quot;send a webhook&quot;.&lt;/p&gt;

&lt;p&gt;Furthermore, even &lt;em&gt;matching on files in a directory&lt;/em&gt; is next to impossible in Nextcloud flows. It involves tagging the directory, letting Nextcloud add another tag to all files inside it and then matching on that tag.&lt;/p&gt;

&lt;p&gt;So just like I felt that Paperless-ngx doesn&apos;t quite fit my thought model, I&apos;m now under the impression that Nextcloud flows are either completely useless or just not useful for me.&lt;/p&gt;
</description>
        <pubDate>Tue, 22 Jul 2025 00:00:00 +0200</pubDate>
        <link>https://jplitza.de/blog/2025/07/22/document-management-3-scanning-documents.html</link>
        <guid isPermaLink="true">https://jplitza.de/blog/2025/07/22/document-management-3-scanning-documents.html</guid>
        
        
      </item>
      
    
      
      <item>
        <title>Document management, part 2: Nextcloud full text search</title>
        <description>&lt;p&gt;Nextcloud is my favorite piece of self-hosted software. It is so universal that it replaced almost everything else I used before. And I remember my surprise about the simplicity of setting up calendar and contact syncing via CalDAV a decade ago using Nextcloud, compared to earlier self-hosted solutions.&lt;/p&gt;

&lt;p&gt;After &lt;a href=&quot;/blog/2025/07/22/document-management-1-paperless-ngx.html&quot;&gt;my experiments with Paperless-ngx&lt;/a&gt;, I wanted to give one particular feature a go that I didn&apos;t use previously: &lt;a href=&quot;https://github.com/nextcloud/fulltextsearch/wiki&quot;&gt;Full text search&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The reason why I didn&apos;t use that feature earlier is simple: Its official implementation requires you to set up an Elasticsearch server. I&apos;m sure that&apos;s a great fit for enterprise usage of Nextcloud, and in my dayjob I operated several Elasticsearch clusters of various sizes. But in the family IT, that software seems very much overkill - both in terms of resource requirements as well as skill and time required to operate.&lt;/p&gt;

&lt;p&gt;What always amused me was that the Nextcloud engineers were considerate enough to make the whole framework very modular - provider apps provide the content to be indexed, platform apps implement the indexing and searching - and yet nobody every implemented another platform app than the official Elasticsearch one! There certainly is other software specialized on searching (Solr comes to my mind), and usually someone somewhere then implements an integration into a software so popular as Nextcloud. But not in this case.&lt;/p&gt;

&lt;p&gt;My idea, however, was much simpler. Nextcloud already has a database backend, why not use it for searching? I knew MySQL had full text search capabilities, so I assumed PostgreSQL did as well, usually being the more advanced competitor in my impression. I didn&apos;t even know what other backends were supported, but surely supporting those most widely used would be most important!&lt;/p&gt;

&lt;p&gt;So I dove into a jungle of code, split up between the Nextcloud server core (where - surprisingly - all of the interface definitions lived), the fulltextsearch app and the fulltextsearch_elasticsearch app. Along the way I found more and more documentation for Nextcloud developers, especially about how database access worked. But nothing really explained the whole thought model around the full text search framework with its services, runners and interfaces. So I was left with only one option: Hack away and see where it leads!&lt;/p&gt;

&lt;p&gt;Well, it lead to the first ever Nextcloud app by yours truly: &lt;a href=&quot;https://github.com/jplitza/fulltextsearch_sql&quot;&gt;fulltextsearch_sql&lt;/a&gt;. It does exactly what I imagined, and it does so quite well actually!&lt;/p&gt;

&lt;p&gt;Of course this is a mere proof of concept. The code is a spaghetti mess and the number of TODOs riddled throughout the code and issues on Github speak for themselves. I still haven&apos;t wrapped my head around the concepts of tags, substags, metatags, parts and multiple excerpts. And yet… it works! And I probably will even keep using it on my personal instance.&lt;/p&gt;

&lt;p&gt;I&apos;m currently in the process of submitting it to the official app catalog. We&apos;ll see if and when that works out…&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update:&lt;/em&gt; After more than a week, my &lt;a href=&quot;https://github.com/nextcloud/app-certificate-requests/pull/811&quot;&gt;certificate request pull request&lt;/a&gt; was finally merged, enabling me to submit the app. So you can now &lt;a href=&quot;https://apps.nextcloud.com/apps/fulltextsearch_sql&quot;&gt;find it in the Search category&lt;/a&gt; of installable apps on your Nextcloud instance! I also spent some time automating E2E tests and app release with Github Actions and actually implementing PostgreSQL support (based on those tests, since my Nextcloud uses MySQL).&lt;/p&gt;

&lt;h3 id=&quot;frontend&quot;&gt;Frontend&lt;/h3&gt;

&lt;p&gt;Now that I had a working full text search backend, I was able to try and actually use it - after what felt like an eternity of indexing. But it turns out the front end for full text search in Nextcloud is suprisingly… rough? Every result is prefixed with &quot;(files)&quot; to indicate the content provider it belongs to. In a fully localized application, that feels out of place.&lt;/p&gt;

&lt;p&gt;When the excerpt the (my) platform app provides is too long for the available screen space, it&apos;s truncated &lt;em&gt;in the middle&lt;/em&gt;, where the searched term is most likely to show up. So maybe my understanding what an excerpt should be differs from what Elasticsearch provides…&lt;/p&gt;

&lt;p&gt;And that&apos;s only in the webinterface. I opened &lt;a href=&quot;https://github.com/nextcloud/android/issues/15233&quot;&gt;a bug report to the Android app&lt;/a&gt; because depending on a server setting, it opens search results in the browser instead of the app itself. Ironically, the setting in question is called &quot;Open files directly from search results&quot;. Luckily, I can just turn it off, and everything works as it should.&lt;/p&gt;

&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;All in all, the full text search experience with Nextcloud isn&apos;t great, but it seems to work without requiring additional software. Now I just need to export everything I put exclusively into Paperless-ngx in the last few months to my old folder structure in order to really compare the two solutions.&lt;/p&gt;
</description>
        <pubDate>Tue, 22 Jul 2025 00:00:00 +0200</pubDate>
        <link>https://jplitza.de/blog/2025/07/22/document-management-2-nextcloud-fulltextsearch.html</link>
        <guid isPermaLink="true">https://jplitza.de/blog/2025/07/22/document-management-2-nextcloud-fulltextsearch.html</guid>
        
        
      </item>
      
    
      
      <item>
        <title>Document management, part 1: Paperless-ngx</title>
        <description>&lt;p&gt;Nobody likes paper folders. And although I don&apos;t expect having to move ever again, if I do, I don&apos;t want to carry boxes of them around. So I set out to finally digitize all of them.&lt;/p&gt;

&lt;p&gt;When looking for self-hosted document management software, everybody seems to be using Paperless-ngx nowadays. It&apos;s the successor to the discontinued Paperless-ng, which was the successor to the discontinued Paperless. (Wonder what the next reincarnation will be called…)&lt;/p&gt;

&lt;p&gt;So naturally I checked out why everybody loved this piece of software. And it does have its advantages:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Simple automatic OCR of scanned PDFs&lt;/li&gt;
  &lt;li&gt;Automatic creation date recognition&lt;/li&gt;
  &lt;li&gt;Automatic assignment of correspondents, tags and other metadata based on heuristics&lt;/li&gt;
  &lt;li&gt;Full text search&lt;/li&gt;
  &lt;li&gt;Arbitrarily complex metadata for every document&lt;/li&gt;
  &lt;li&gt;Automatic import of files from a “consume” directory, to which a script puts everything my scanner scans&lt;/li&gt;
  &lt;li&gt;An inbox of documents that yet have to be categorized&lt;/li&gt;
  &lt;li&gt;Side-by-side view of editable metadata and document for easy entry of metadata&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But after using it for a while, I don&apos;t consider it the right fit for my needs.&lt;/p&gt;

&lt;h3 id=&quot;finding-documents&quot;&gt;Finding documents&lt;/h3&gt;

&lt;p&gt;I often find myself wondering “What was the name of that insurance company again?” just to find their latest invoice.&lt;/p&gt;

&lt;p&gt;In my previous setup, I just had a folder structure like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Insurances/Company Name/YYYY-MM-DD Invoice.pdf&lt;/code&gt;. Having a list of ~10 insurance companies to pick from is much easier than remembering it from scratch (or looking through ~100 correspondents in total).&lt;/p&gt;

&lt;p&gt;Now you could associate so called “storage paths” with documents in Paperless-ngx that would cause the PDFs to have this exact same layout on disk. Or you could associate tags with the documents. And you can also automate all that. But it doesn&apos;t beat the simplicity and accessibility of nested folders…&lt;/p&gt;

&lt;h3 id=&quot;metadata-creep&quot;&gt;Metadata creep&lt;/h3&gt;

&lt;p&gt;When I said “arbitrarily complex metadata”, I referred to the ability to create custom metadata fields. But I don&apos;t need any of those! In fact, I don&apos;t even need those metadata fields that Paperless-ngx has built-in. Why would I care about the “document type“ of a document? Its title probably says it all! And those storage paths seem inferior to simply folders of files, as mentioned above.&lt;/p&gt;

&lt;p&gt;Now of course I could simply ignore those fields. But then I feel like I&apos;m holding it wrong! So I always try to come up with reasonable values at least for the document type, although I never use that field at all.&lt;/p&gt;

&lt;h3 id=&quot;access-control&quot;&gt;Access control&lt;/h3&gt;

&lt;p&gt;Last but definitely not least is access control.&lt;/p&gt;

&lt;p&gt;I&apos;m sure there are situations where fine grained access control is useful. For example in a business setting, with departments and everything.&lt;/p&gt;

&lt;p&gt;But my instance is to be used by exactly two people: Me wife and me. And we&apos;re coming from a digital folder we both have access to and paper folders we both have access to. So I would simply want everything to be available to her as well.&lt;/p&gt;

&lt;p&gt;But apparently, that&apos;s surprisingly hard. Every document has its own permissions. So does every correspondent. And while I could grant her “Superuser“ rights, that would eliminate the &lt;em&gt;possibility&lt;/em&gt; of every having different views of the system - which might come in handy at some point.&lt;/p&gt;

&lt;p&gt;Another curiosity: Documents imported from the “consume” directory don&apos;t have an owner and can be accessed by &lt;em&gt;everyone&lt;/em&gt;!&lt;/p&gt;

&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;Paperless-ngx is a great piece of software! But somehow, it doesn&apos;t fit my thought model, which seems to be very centered around classical folders.&lt;/p&gt;

&lt;p&gt;Also, I&apos;m in the process of simplifying my private IT infrastructure in order for it to be easier to maintain. And introducing another application doesn&apos;t quite seem justified.&lt;/p&gt;

&lt;p&gt;What I definitely don&apos;t want to miss are full text search and automatic import and OCR of scanned documents. But I&apos;ll try to implement that in Nextcloud, which I have anyway and will very likely keep. We&apos;ll see how that works out, stay tuned…&lt;/p&gt;
</description>
        <pubDate>Tue, 22 Jul 2025 00:00:00 +0200</pubDate>
        <link>https://jplitza.de/blog/2025/07/22/document-management-1-paperless-ngx.html</link>
        <guid isPermaLink="true">https://jplitza.de/blog/2025/07/22/document-management-1-paperless-ngx.html</guid>
        
        
      </item>
      
    
      
      <item>
        <title>AirCO₂ntrol in Home Assistant</title>
        <description>&lt;p&gt;Auf &lt;a href=&quot;https://twitter.com/nblr/status/1462814024782028810&quot;&gt;Empfehlung von @nblr&lt;/a&gt; hin habe ich mir über meinen Arbeitgeber
(vielen Dank an dieser Stelle) den CO₂-Sensor „&lt;a href=&quot;https://www.tfa-dostmann.de/produkt/co2-monitor-airco2ntrol-mini-31-5006/&quot;&gt;AirCO₂ntrol Mini&lt;/a&gt;“ der
Firma TFA Dostmann besorgt. Neben drei farbigen LEDs, deren Übergänge bei 800ppm
und 1200ppm liegen, hat er die Besonderheit, dass er über seine Messwerte
(Temperatur und eben die CO₂-Konzentration) auch per USB Auskunft erstattet!&lt;/p&gt;

&lt;p&gt;Der ursprünglich von @nblr verlinkte &lt;a href=&quot;https://hackaday.io/project/5301-reverse-engineering-a-low-cost-usb-co-monitor&quot;&gt;hackaday-Artikel&lt;/a&gt; erwies sich als
wenig hilfreich,  da er am Ende nicht funktionierte. Aber nach genug etwas
Suchen fand ich noch diverse andere Lösungen. Eine davon schien mir für meinen
Anwendungszweck tauglich: Der Sensor sollte nämlich am OpenWrt-Router im
Arbeitszimmer hängen, und darauf erst mal 1000 Abhängigkeiten zu installieren
ist bekanntlich schwierig. &lt;a href=&quot;https://gist.github.com/librarian/306e06c51fe5f53ded6ebc761580b62b&quot;&gt;Dieses Python-Script&lt;/a&gt; hatte derer aber recht
wenige und war simpel genug, es mal eben so umzubauen, dass es die Messwerte via
&lt;del&gt;MQTT&lt;/del&gt; HTTP statt via stdout mitteilt.&lt;/p&gt;

&lt;p&gt;Und so sendet jetzt &lt;a href=&quot;https://gist.github.com/jplitza/3fdbc9f24df3e75305f4b047fbc8ddae&quot;&gt;mein Fork&lt;/a&gt; alle paar Sekunden die aktuelle
CO₂-Konzentration und Temperatur im Arbeitszimmer an meinen &lt;a href=&quot;https://www.home-assistant.io/&quot;&gt;Home Assistant&lt;/a&gt;.
Das erzeugt schöne Graphen, für mehr nutze ich das aber tatsächlich noch nicht,
denn die LED-Ampel reicht mir aus um ans Lüften erinnert zu werden. Und das ist
bei einem etwa 12m³ großen Raum schneller nötig als mir lieb ist, besonders wenn
die Tür zu ist…&lt;/p&gt;

&lt;figure class=&quot;image&quot;&gt;
    &lt;a href=&quot;/blog/files/2021-12-08-graph_co2.png&quot;&gt;
        &lt;img src=&quot;/blog/files/2021-12-08-graph_co2.png&quot; alt=&quot;Graph der CO₂-Konzentration im Laufe eines Arbeitstages&quot; /&gt;
    &lt;/a&gt;

    &lt;figcaption&gt;Graph der CO₂-Konzentration im Laufe eines Arbeitstages&lt;/figcaption&gt;

&lt;/figure&gt;

&lt;p&gt;&lt;em&gt;Update 10.10.2022:&lt;/em&gt; Da mir das Python auf dem OpenWrt-Router zu viel Platz
weggenommen hat bin ich auf Micropython umgestiegen und nutze jetzt die HTTP API
von Home Assistant statt MQTT.&lt;/p&gt;
</description>
        <pubDate>Wed, 08 Dec 2021 00:00:00 +0100</pubDate>
        <link>https://jplitza.de/blog/2021/12/08/airco2ntrol-in-home-assistant.html</link>
        <guid isPermaLink="true">https://jplitza.de/blog/2021/12/08/airco2ntrol-in-home-assistant.html</guid>
        
        
      </item>
      
    
      
      <item>
        <title>My DNS setup with PowerDNS</title>
        <description>&lt;p&gt;I recently overhauled my DNS setup (recursive for my home network and
authoritative for my domains), so why not blog about it?&lt;/p&gt;

&lt;p&gt;Let’s start with the requirements, which are kind of special. I host all my
stuff at home behind a DSL line, and while I have a VPN with a static IP address
as well, I don’t want to tunnel everything through it. Thus, I need dynamically
updatable DNS records for almost everything.&lt;/p&gt;

&lt;p&gt;Furthermore, I want my home network to be able to resolve my domains even when
the internet connection is broken (or stated differently: I don’t want the
requests to hit the internet).&lt;/p&gt;

&lt;p&gt;Hence, I’m need a combined recursive and authoritative server. The recursive
part, however, has some quirks of its own: I want to be able to resolve
non-standard community-TLDs like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.dn42&lt;/code&gt; in the VPN-based overlay networks I’m
part of. But at the same time, I want the “usual” DNS to be DNSSEC-validated.
Together, this requires the ability to have so called “negative trust anchors”,
or NTAs for short. They state that some part of the DNS must not be
DNSSEC-validate, come whatever may. Otherwise, I could advise the DNS recursor
to look for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.dn42&lt;/code&gt; at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;172.23.0.53&lt;/code&gt;, but it would refuse to answer any requests
for it because the DNSSEC-signed root zone says there no &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.dn42&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Previously, I was using bind for the authoritative part. But because bind is
incapable of having configurable NTAs&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot; role=&quot;doc-noteref&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, it used &lt;a href=&quot;https://unbound.net/&quot;&gt;unbound&lt;/a&gt; as recursor. This
was kind of cumbersome and involved every request passing through two daemons
with two caches. I chose bind because it was (and AFAIK still is) the only
software that is able to DNSSEC-sign zones if it only has the ZSK, not the KSK,
which I only had on my laptop. However, as my laptop is now backed up on my home
server anyway, I got rid of this level of paranoia and looked at other software
again.&lt;/p&gt;

&lt;p&gt;In other contexts I very successfully used &lt;a href=&quot;https://powerdns.com/&quot;&gt;PowerDNS&lt;/a&gt;, and hence I set forth to
replace the legacy combination with a nice pdns and pdns_recursor. And indeed:
It works like a charm!&lt;/p&gt;

&lt;p&gt;What’s more, there’s hardly anything interesting about the config that I could
mention here: It just works!™ Okay, it’s a bit more than that. Especially that
much of what I considered configuration takes place in the database. But nothing
I had to do was out of the ordinary, and I found everything I needed in the
extremely good &lt;a href=&quot;https://doc.powerdns.com/&quot;&gt;documentation&lt;/a&gt;. Compare that to bind, where every documentation
is incomprehensible or incomplete.&lt;/p&gt;

&lt;p&gt;And on the way, I got some nice tools like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pdnsutil edit-zone&lt;/code&gt;. Hooray!&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;In newer versions you can inject them during runtime, but they aren’t preserved across restarts. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Sun, 30 Dec 2018 00:00:00 +0100</pubDate>
        <link>https://jplitza.de/blog/2018/12/30/dns-setup-with-powerdns.html</link>
        <guid isPermaLink="true">https://jplitza.de/blog/2018/12/30/dns-setup-with-powerdns.html</guid>
        
        
      </item>
      
    
      
      <item>
        <title>Bonding Wifi interfaces with Network Manager</title>
        <description>&lt;p&gt;For a long time, it bothered me that transitioning from network cable to Wifi
caused a loss of all persistent connections. SSH being the most painful, others
were noticable too (streams, chat, …).&lt;/p&gt;

&lt;p&gt;After upgrading to Ubuntu 18.04, I noticed that Network Manager has the ability
to control bonding devices. Maybe it gained this ability even earlier, but I
just noticed it now. What Linux calls bonding, others teaming, port channel or
link aggregation group, is usually used with multiple cables to increase
throughput, reliability or both of mostly servers. The different modes decide
which packets are sent out which “slave” interface, sometimes in cooperation with
the switches they are connected to, sometimes without. So why not use bonding to
bond the ethernet and Wifi cards in active-backup mode?&lt;/p&gt;

&lt;p&gt;Problem was, the GUI of Network Manager apparently doesn’t want you to bond wifi
interfaces. Manually, using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ip link&lt;/code&gt;, I was able to configure the desired bond.
But ditching Network Manager altogether makes managing Wifi networks really
cumbersome. So after digging around a bit, I found the holy grail:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nmcli conn modify &lt;span class=&quot;s2&quot;&gt;&quot;Wifi connection&quot;&lt;/span&gt; connection.master bond0 connecion.slave-type bond
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This simply adds the already configured wifi connection as a slave to the
already configured active-backup bond connection. You can even use the GUI
afterwards to mange both, it’s just this link that cannot be created with the
GUI.&lt;/p&gt;

&lt;p&gt;Now, I can dock and undock my laptop without losing all SSH connections. ☺&lt;/p&gt;
</description>
        <pubDate>Mon, 24 Sep 2018 00:00:00 +0200</pubDate>
        <link>https://jplitza.de/blog/2018/09/24/bonding-wifi-interfaces.html</link>
        <guid isPermaLink="true">https://jplitza.de/blog/2018/09/24/bonding-wifi-interfaces.html</guid>
        
        
      </item>
      
    
      
      <item>
        <title>Was mit Holz</title>
        <description>&lt;p&gt;Ich habe die letzten beiden Wochenenden auch mal #WasMitHolz gemacht: Einen
Wickelkommoden-Aufsatz! Den Plan hatte ich gefasst, sobald klar wurde, dass wir
eine Wickelkommode brauchen und keine Kommode passender Höhe haben. „Der Plan“
sah dabei so aus:&lt;/p&gt;

&lt;figure class=&quot;image&quot;&gt;
    &lt;a href=&quot;/blog/files/2018-06-diagram.png&quot;&gt;
        &lt;img src=&quot;/blog/files/2018-06-diagram.png&quot; alt=&quot;Hochprofessionelle Skizze der Konstruktion&quot; /&gt;
    &lt;/a&gt;

    &lt;figcaption&gt;Hochprofessionelle Skizze der Konstruktion&lt;/figcaption&gt;

&lt;/figure&gt;

&lt;p&gt;Ich habe mich davor gedrückt, irgendetwas selbst sägen zu müssen, da ich weder
Werkbank noch vernünftige Säge besitze. Die Platten wurden also alle bereits im
Baumarkt passend zugesägt. Also… alle bis auf eine, da ich leider das „2×“ in
der Liste geflissentlich ignoriert habe. Also sah das Projekt nach dem ersten
Anlauf erst mal nur so aus:&lt;/p&gt;

&lt;figure class=&quot;image&quot;&gt;
    &lt;a href=&quot;/blog/files/2018-06-holz1.jpg&quot;&gt;
        &lt;img src=&quot;/blog/files/2018-06-holz1.jpg&quot; alt=&quot;Work in Progress…&quot; /&gt;
    &lt;/a&gt;

    &lt;figcaption&gt;Work in Progress…&lt;/figcaption&gt;

&lt;/figure&gt;

&lt;p&gt;Eine Woche später hatte ich auch die fehlende Platte (und etwas Zubehör vom
Schweden) und konnte das Ganze fertigstellen:&lt;/p&gt;

&lt;figure class=&quot;image&quot;&gt;
    &lt;a href=&quot;/blog/files/2018-06-holz2.jpg&quot;&gt;
        &lt;img src=&quot;/blog/files/2018-06-holz2.jpg&quot; alt=&quot;Fertiger Aufsatz&quot; /&gt;
    &lt;/a&gt;

    &lt;figcaption&gt;Fertiger Aufsatz&lt;/figcaption&gt;

&lt;/figure&gt;

</description>
        <pubDate>Wed, 06 Jun 2018 00:00:00 +0200</pubDate>
        <link>https://jplitza.de/blog/2018/06/06/was-mit-holz.html</link>
        <guid isPermaLink="true">https://jplitza.de/blog/2018/06/06/was-mit-holz.html</guid>
        
        
      </item>
      
    
      
      <item>
        <title>My Multi-Room Music Setup</title>
        <description>&lt;p&gt;For much too long, I wanted to write about how I completely overhauled our
multi-room audio setup at home about a year ago.&lt;/p&gt;

&lt;p&gt;Previously, the setup was as follows: We had four sets of speakers, distributed
in the different rooms of our apartment, and they were all connected to the
HP Microserver that played the music using &lt;a href=&quot;https://www.musicpd.org/&quot;&gt;MPD&lt;/a&gt; and Pulseaudio via a copper
cable and a USB DAC. The obvious downside to this approach is its lack of
scalability: Each room required a dedicated cable to the server, and the 7.1 USB
DAC that I tricked into playing the same stereo stream on every of its four mini
jack plugs. The less obvious downside is the lack of surge protection on copper
audio cables.&lt;/p&gt;

&lt;p&gt;So when I decided to move the server to another place in the apartment and equip
it with a UPS (and thus surge protection, on the power line as well as on the
Ethernet side), I was looking for a new solution. The main requirement was
synchronicity: While standing in the hallway, I want to have exactly synchronous
audio from all rooms. That’s what Pulseaudio was for in the old setup, as I
couldn’t get ALSA to do the job well enough.&lt;/p&gt;

&lt;p&gt;Secondly, to achieve surge protection on all wires towards the server, it seemed
like a good idea to use something Ethernet-based (obviously requiring some
playing device in every room).&lt;/p&gt;

&lt;p&gt;Enter &lt;a href=&quot;https://github.com/badaix/snapcast&quot;&gt;Snapcast&lt;/a&gt;. In a traditional server-client architecture, this little piece
of software offers exactly that: Streaming time-synchronized audio from a FIFO
on the server to multiple clients’ speakers. The performance is topped off by an
Android app that can be used as both, a client and a remote control for the
various volume levels. And with the buffers all tuned to low, the delay when
starting and stopping music is only minimal.&lt;/p&gt;

&lt;p&gt;Dusting off some old &lt;a href=&quot;https://www.raspberrypi.org/&quot;&gt;Raspberry Pi&lt;/a&gt;s model B, the (far from hi-fi) playback
hardware was settled. But because I don’t want to update a couple of Raspbians
every day for no apparent reason (remember, they run a single daemon in a sealed
off network and only every connect to my own server), I went ahead and toyed
around with &lt;a href=&quot;https://buildroot.org/&quot;&gt;Buildroot&lt;/a&gt; and its Snapcast-addon &lt;a href=&quot;https://github.com/badaix/snapos&quot;&gt;SnapOS&lt;/a&gt;. And for a software guy
like myself, that’s where the real fun began: How fast can I get the Pis to play
music after powering them up? Or, as next best optimization goal: How small can
I get the image?&lt;/p&gt;

&lt;p&gt;Well, I won’t say that I’ve attained the optimum, but I’m satisfied by the
current solution: My &lt;a href=&quot;https://github.com/jplitza/snapcast_satellite&quot;&gt;snapcast satellite&lt;/a&gt; configuration (currently) produces a
1.1 MiB kernel (XZ compressed) and a 3.9 MiB initramfs (uncompressed) that takes
around 15 seconds to boot and play music, fetching all its configuration
(network details, hostname, NTP and Snapcast servers) via DHCP. Only my SSH key
is “hardcoded”.&lt;/p&gt;

&lt;p&gt;So two of the rooms now have Rasberry Pis for playback, the workroom uses my
laptop and – what I like most – the living room the Amazon FireTV (the Android
app also is a client, remember?).&lt;/p&gt;

&lt;p&gt;I was a bit disappointed that I actually needed wired Ethernet for decent
synchronicity, but for some reason I couldn’t get a satisfactory result using
Wifi links. Oh well.&lt;/p&gt;

</description>
        <pubDate>Sat, 07 Apr 2018 00:00:00 +0200</pubDate>
        <link>https://jplitza.de/blog/2018/04/07/multi-room-music-setup.html</link>
        <guid isPermaLink="true">https://jplitza.de/blog/2018/04/07/multi-room-music-setup.html</guid>
        
        
      </item>
      
    
      
      <item>
        <title>GPG attacks</title>
        <description>&lt;p&gt;While communicating with the &lt;a href=&quot;https://ccc.de/office/&quot;&gt;CCC office&lt;/a&gt;, I was informed that they couldn’t
send me GPG encrypted mails because of the error “GPGME: Ambiguous name”. Of
course there is more than one key if you search for my mail address (I had other
keys in the past), but they also quoted my correct key ID.&lt;/p&gt;

&lt;p&gt;Well, turns out &lt;a href=&quot;https://www.heise.de/security/meldung/Haufenweise-Fake-PGP-Schluessel-im-Umlauf-3297175.html&quot;&gt;the GPG key ID collisions that were in the news last
year&lt;/a&gt; also &lt;a href=&quot;https://sks-keyservers.net/pks/lookup?op=search&amp;amp;search=0xD8CCEC27&quot;&gt;caught my key&lt;/a&gt;. While the key with id
&lt;a href=&quot;https://sks-keyservers.net/pks/lookup?op=vindex&amp;amp;search=0xB17F2106D8CCEC27&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xB17F2106D8CCEC27&lt;/code&gt; really is mine&lt;/a&gt; (as I also state on &lt;a href=&quot;/keys/&quot;&gt;my keys
page&lt;/a&gt;), the &lt;a href=&quot;https://sks-keyservers.net/pks/lookup?op=vindex&amp;amp;search=0x5AAD3FC3D8CCEC27&quot;&gt;fake one with long ID &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x5AAD3FC3D8CCEC27&lt;/code&gt;&lt;/a&gt; (notice
the identical last eigth characters) has many of the correct parameters that are
mentioned in the article:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It has the correct primary user ID.&lt;/li&gt;
  &lt;li&gt;It is signed by some other fake keys that correspond to real keys that signed
my real key (like CACert).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, it also lacks some details:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It doesn’t have any secondary user IDs.&lt;/li&gt;
  &lt;li&gt;It has the wrong creation time.&lt;/li&gt;
  &lt;li&gt;Its signatures never expire. CACert only ever signs for one year.&lt;/li&gt;
  &lt;li&gt;And of course, it’s revoked, as it was created by researchers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All in all, I guess I should be proud that apparently, I’m part of the GPG
strong set (as suggested by the article) and surprised that the CCC office
considers revoked keys.&lt;/p&gt;

</description>
        <pubDate>Sun, 27 Aug 2017 00:00:00 +0200</pubDate>
        <link>https://jplitza.de/blog/2017/08/27/gpg-attacks.html</link>
        <guid isPermaLink="true">https://jplitza.de/blog/2017/08/27/gpg-attacks.html</guid>
        
        
      </item>
      
    
  </channel>
</rss>
