<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de_DE"><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://www.deltachaos.de//feed.xml" rel="self" type="application/atom+xml" /><link href="https://www.deltachaos.de//" rel="alternate" type="text/html" hreflang="de_DE" /><updated>2026-08-19T08:54:09+00:00</updated><id>https://www.deltachaos.de//feed.xml</id><title type="html">Maximilian ‘Deltachaos’ Ruta</title><subtitle>Web Entwickler aus Leidenschaft, politisch engagiert, Radiohörer, Vegetarier. Ich schreibe hier über alles was mich bewegt, das aktuelle politische Geschehen, Nerdkarms, und Musik.</subtitle><author><name>Maximilian Ruta</name></author><entry xml:lang="en"><title type="html">DeltaChess: a chess engine rabbit hole inside World of Warcraft</title><link href="https://www.deltachaos.de//it/2026/02/10/deltachess-chess-in-world-of-warcraft.html" rel="alternate" type="text/html" title="DeltaChess: a chess engine rabbit hole inside World of Warcraft" /><published>2026-02-10T17:00:00+00:00</published><updated>2026-02-10T17:00:00+00:00</updated><id>https://www.deltachaos.de//it/2026/02/10/deltachess-chess-in-world-of-warcraft</id><content type="html" xml:base="https://www.deltachaos.de//it/2026/02/10/deltachess-chess-in-world-of-warcraft.html"><![CDATA[<p>It started as a dumb bet with a guildmate:
<strong>“Can you write a fully handwritten chess program in under 7 hours?”</strong></p>

<p>Seven hours later I had something that <em>kind of</em> moved pieces around — a tiny <strong>Python</strong> console program that could draw a
board and accept moves. Nothing fancy. No UI. No clocks. Barely any rules. But it was <em>mine</em>, and it worked enough to be
fun.</p>

<p>Then another friend said the sentence that doomed my free time:</p>

<p><strong>“Okay… but what if this was a World of Warcraft addon?”</strong></p>

<p>And that idea was too good to ignore. So I started over — different language, different constraints, different everything.
The result is <strong>DeltaChess</strong>: chess inside WoW, against other players (including cross‑realm where WoW allows) or against
the computer.</p>

<p>If you want to peek at it later: <a href="https://www.curseforge.com/wow/addons/deltachess">CurseForge</a> / <a href="https://github.com/Deltachaos/DeltaChess">GitHub</a></p>

<h2 id="chess-in-a-place-that-really-doesnt-want-chess">Chess in a place that really doesn’t want chess</h2>

<p>Writing chess code is one thing. Writing chess code in the WoW Lua sandbox is another.</p>

<p>In Python on the console, “just compute for a bit longer” is an acceptable strategy. In WoW, it’s a great way to make the
game hitch and drop frames. So the project quickly became about constraints:</p>

<ul>
  <li><strong>Rules correctness</strong>: castling, en passant, promotion, draw rules… the boring parts that make it “real chess”.</li>
  <li><strong>Responsiveness</strong>: engines must <strong>yield</strong> work so the game keeps rendering smoothly.</li>
  <li><strong>Determinism and safety</strong>: don’t crash your UI because an engine tried something illegal.</li>
</ul>

<p>Here’s what the board looks like today:</p>

<p><img src="/assets/images/2026/02/deltachess-board.png" alt="DeltaChess board view" /></p>

<p>And the “play vs computer” flow that wires the UI into the engine framework:</p>

<p><img src="/assets/images/2026/02/deltachess-vs-computer.png" alt="DeltaChess vs computer dialog" /></p>

<p>PGN export was a must-have (because what’s the point of blundering in WoW if you can’t paste it into Lichess later?):</p>

<p><img src="/assets/images/2026/02/deltachess-pgn-export.png" alt="DeltaChess PGN export" /></p>

<h2 id="the-part-i-didnt-expect-i-actually-learned-chess-programming">The part I didn’t expect: I actually learned chess programming</h2>

<p>I used a fair amount of AI assistance for UI and addon glue code, but the engine side pulled me into the classic chess
programming rabbit hole: search, evaluation tradeoffs, move generation pitfalls, and performance tricks you only learn
once you can <em>feel</em> the branching factor.</p>

<p>Some highlights of what I ended up (re-)learning:</p>

<ul>
  <li><strong>UCI (Universal Chess Interface)</strong>: the lingua franca for “engine talks to GUI”.
I built a small UCI wrapper so I could run and test the Lua engines from the outside world (and compare behaviors).</li>
  <li><strong>Minimax → Negamax</strong>: switching from “two-player min/max” to “one function + sign flip” is one of those “why didn’t I
do this earlier?” moments.</li>
  <li><strong>Alpha–Beta pruning</strong>: the first time you watch node counts collapse because your move ordering improved, it’s
addictive.</li>
</ul>

<p>And on a purely personal level: it was a nice excuse to refresh my <strong>Lua</strong> knowledge (including the parts you only
remember once you write something non-trivial and performance-sensitive).</p>

<h2 id="a-pluggable-async-engine-framework-because-wow-demands-it">A pluggable, async engine framework (because WoW demands it)</h2>

<p>DeltaChess ships with a small engine framework that tries to make the hard parts boring:</p>

<ul>
  <li>Engines are <strong>stateless</strong>: each calculation gets a position + options; no hidden global state required.</li>
  <li>The runner is <strong>single-threaded and async</strong>: engines can yield via a callback so computations spread across frames.</li>
  <li>Every move is validated: if an engine returns an illegal move, it’s caught immediately.</li>
</ul>

<h3 id="the-real-reason-the-framework-exists-testing-outside-of-wow">The real reason the framework exists: testing outside of WoW</h3>

<p>One of the biggest practical problems early on wasn’t even search or evaluation — it was <strong>testing</strong>.</p>

<p>Inside WoW I couldn’t easily run automated tests that would tell me whether an engine always produces <strong>legal</strong> moves,
and whether the move generator behaves <strong>consistently</strong> across thousands of positions. Debugging that kind of thing by
hand, in a UI, is misery.</p>

<p>So I extracted the whole “business logic” (rules + move generation) <em>and</em> the engines into a separate project that can
run completely outside the WoW environment. That gave me a proper <strong>automated test suite</strong> where engines can self-play
and every returned move is validated for legality.</p>

<p>The framework also supports <strong>ELO-based difficulty selection</strong> and ships with four engines spanning roughly beginner to
very strong:</p>

<table>
  <thead>
    <tr>
      <th>Engine</th>
      <th>Notes</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>Dumb Goblin</strong></td>
      <td>“Capture the highest thing” style — great for absolute beginners</td>
    </tr>
    <tr>
      <td><strong>Sunfish</strong></td>
      <td>MTD-bi + iterative deepening + transposition tables</td>
    </tr>
    <tr>
      <td><strong>GarboChess</strong></td>
      <td>Alpha–beta with classic pruning/ordering heuristics (null move, killers, SEE, …)</td>
    </tr>
    <tr>
      <td><strong>Fruit 2.1</strong></td>
      <td>A historically influential engine with a bag of serious search tricks (LMR, history heuristics, tapered eval, …)</td>
    </tr>
  </tbody>
</table>

<p>Huge thanks to <strong>Chessforeva</strong> and their Lua chess work, especially the <a href="https://github.com/Chessforeva/Lua4chess"><code class="language-plaintext highlighter-rouge">Lua4chess</code></a>
repository. They had already ported several classic engines to Lua, which made them <em>way</em> easier to integrate.</p>

<p>There was one catch though: those ports were written in a more “normal” style where you just… calculate until you’re
done. In WoW’s single-threaded UI, that meant the game could hang for several seconds whenever an engine thought too long.</p>

<p>So a big chunk of the project ended up being <strong>rewriting/adapting the engines</strong> to allow <strong>async execution</strong> in an event
loop: do some work, yield, resume next frame, repeat — so the game stays responsive while the engine is searching.</p>

<p>If you’re curious, the engine framework lives here: <a href="https://github.com/Deltachaos/deltachess-engine-framework">deltachess-engine-framework</a></p>

<h2 id="where-im-stuck-elo-calibration-for-slow-lua-engines">Where I’m stuck: ELO calibration for slow Lua engines</h2>

<p>This is the part where I’d love advice from people who have done this “for real”.</p>

<p>The engines are written in <strong>Lua</strong> (because WoW), so they’re <em>slow</em> compared to typical C/C++ engines. I tried running
tournaments via cutechess, but getting anything remotely stable takes an absurd amount of time.</p>

<p>My goal isn’t perfect scientific accuracy—I just want players to pick an AI opponent that roughly matches their strength,
instead of random “difficulty” labels.</p>

<p>So if you have experience with engine testing and rating, I’d appreciate any pointers:</p>

<ul>
  <li>Are there smarter ways to <strong>estimate / approximate ELO</strong> for slow engines without weeks of round-robin games?</li>
  <li>Any good approaches for <strong>calibrating across very different environments</strong> (fast desktop vs WoW sandbox)?</li>
  <li>Any tricks for <strong>cutting down match counts</strong> without totally ruining the numbers (SPR T-tests, sequential testing,
smarter opponent selection, etc.)?</li>
</ul>

<p>If you try DeltaChess, skim the code, or have “don’t do this, it’s a bad idea” comments—please let me know. This was
never meant to be a serious engine project, but it definitely pushed me down the rabbit hole, and I’d love to learn
more.</p>]]></content><author><name>Maximilian Ruta</name></author><category term="it" /><summary type="html"><![CDATA[It started as a dumb bet with a guildmate: “Can you write a fully handwritten chess program in under 7 hours?”]]></summary></entry><entry xml:lang="en"><title type="html">My Thoughts on the State Election Results</title><link href="https://www.deltachaos.de//politik/2024/09/01/my-thoughts-on-the-state-election-results.html" rel="alternate" type="text/html" title="My Thoughts on the State Election Results" /><published>2024-09-01T17:00:00+00:00</published><updated>2024-09-01T17:00:00+00:00</updated><id>https://www.deltachaos.de//politik/2024/09/01/my-thoughts-on-the-state-election-results</id><content type="html" xml:base="https://www.deltachaos.de//politik/2024/09/01/my-thoughts-on-the-state-election-results.html"><![CDATA[<h2 id="the-firewall-against-the-afdand-its-weaknesses">The “Firewall” Against the AfD—and Its Weaknesses</h2>

<p>The so‑called “firewall” against the AfD cannibalizes itself through an involuntary “marriage” of partners who have
hardly anything in common—until it eventually breaks. Unfortunately, that reminds me of 1939.</p>

<h2 id="rejection-of-migration-causes-and-consequences">Rejection of Migration: Causes and Consequences</h2>

<p>We have to accept—and acknowledge—that people in Germany no longer want immigration. There are various reasons for this:
the country being overwhelmed by more than 2.5 million refugees over the last ten years, the emergence of parallel
societies, and the erosion of people’s sense of fairness and justice.</p>

<h2 id="political-failure-and-the-erosion-of-fairness">Political Failure and the Erosion of Fairness</h2>

<p>That this sense of fairness has eroded is the responsibility of the political actors of recent years. Under the grand
coalitions, action against precarious employment conditions happened only in “homeopathic” steps for a long time.
Meaningful improvements for those who have the least are not broadly supported, because the working middle feels
overburdened—by inflation, the heating law, and the threat of job loss. The impression is spreading that work no longer
pays off in this country.</p>

<h2 id="bureaucracy-and-hostility-toward-business-as-a-brake-on-growth">Bureaucracy and Hostility Toward Business as a Brake on Growth</h2>

<p>Businesses get stones thrown in their way instead of tailwinds, and every year they’re burdened with even more
bureaucracy. Anyone who wants to build a new production hall should beware: if you’re not Intel or Elon Musk, you have
to wrestle with pointless rules and excessive regulations on fire safety, energy retrofits, archaeology, and more. This
snail’s pace is only surpassed by government projects. Today we build bridges at a speed at which entire neighborhoods
used to be constructed. We need a clear‑cutting of our jungle of laws and regulations, and a massive slimming‑down of
bureaucracy.</p>

<h2 id="the-danger-of-simple-solutionsand-the-way-forward">The Danger of Simple Solutions—and the Way Forward</h2>

<p>The “simple solution” promoted by right‑wing parties is to kick downward. That may briefly satisfy an enraged middle,
but it endangers social peace. The solution must be to improve conditions in the low‑wage sector and for the middle of
society—for example by raising the minimum wage.</p>

<h2 id="loss-of-trust-in-governing-parties">Loss of Trust in Governing Parties</h2>

<p>In the face of all these problems, it currently feels like almost all parties are closing their eyes. People have simply
lost trust that the governing parties of the last decades are capable of solving these issues.</p>

<h2 id="so-what-now">So What Now?</h2>

<p>Germany stands at a crossroads, and radical measures are required immediately. The paralyzing mills of bureaucracy must
be dismantled without further delay. Laws must be streamlined to remove the bureaucratic superstructure that hinders
business and innovation. Penalties for violent crimes must be tightened drastically, and we need more funding and staff
for our police to guarantee public safety without curtailing civil liberties.</p>

<p>A stepwise increase of the minimum wage is urgently needed to restore social justice and economic fairness. Necessary
innovations to protect our planet must be accelerated through significantly higher CO₂ taxation. This will only be
accepted if every cent is paid back out as a climate dividend (energy money), with additional support for lower‑income
groups.</p>

<p>On migration policy, immediate action is required: asylum procedures must not take longer than a few months, and taking
up work in skilled trades and healthcare must be enabled right away. At the same time, consistent measures must be
taken against rejected asylum seekers if they reject our societal values—this includes consistent deportations, so that
those who truly enrich our society, or who genuinely need our protection, can stay.</p>

<p>It’s high time we implement these necessary reforms. Germany can’t afford to keep hesitating.</p>]]></content><author><name>Maximilian Ruta</name></author><category term="politik" /><summary type="html"><![CDATA[The “Firewall” Against the AfD—and Its Weaknesses]]></summary></entry><entry xml:lang="en"><title type="html">Kubernetes Rancher in LXC on Proxmox - The container matroska part 2</title><link href="https://www.deltachaos.de//it/2022/03/12/rancher-kubernetes-on-proxmox-lxc.html" rel="alternate" type="text/html" title="Kubernetes Rancher in LXC on Proxmox - The container matroska part 2" /><published>2022-03-12T16:00:00+00:00</published><updated>2022-03-12T16:00:00+00:00</updated><id>https://www.deltachaos.de//it/2022/03/12/rancher-kubernetes-on-proxmox-lxc</id><content type="html" xml:base="https://www.deltachaos.de//it/2022/03/12/rancher-kubernetes-on-proxmox-lxc.html"><![CDATA[<p>About one year ago I have written an article on how to get Racher running in an LXC container on a Proxmox node. I
managed to get it running and described the required steps in <a href="/it/2021/03/10/rancher-in-lxc.html">this article</a>.</p>

<p>What I did not manage to get running was adding a cluster in Rancher using LXC nodes. I left the topic aside and moved
on to other things. I had a lot of other projects in the meantime with Rachner and Kubernetes in general, and now wanted
to finally start using it for my own infrastructure.</p>

<p>Sure I could have accepted that Kubernetes is not running in LXC and used KVM based nodes to run a cluster.
But I did not. There must be a way. Others are running Kubernetes as well in LXC containers. And resource usage, as well
as backup is so much more efficient when using LXC containers.</p>

<h2 id="no-final-success-yet">No final success (yet)</h2>

<p>Before you expect to find the final solution in this blog post, I must disappoint you. I have solved
a few problems so far but still did not manage to bring up a final cluster (yet). If you have any
ideas after reading this, how to get it done, please let me know.</p>

<p>The problem I was facing at the end is, that I was stuck at the error
“network plugin is not ready: cni config uninitialized”.</p>

<h2 id="the-reason-for-the-problems">The reason for the problems</h2>

<p>The main difference between KVM and LXC is that containers are sharing the kernel with the host. Also there is no
virtualization of devices. It behaves more like an advanced <code class="language-plaintext highlighter-rouge">chroot</code>. This means access to <code class="language-plaintext highlighter-rouge">/proc</code>, <code class="language-plaintext highlighter-rouge">/sys</code> and <code class="language-plaintext highlighter-rouge">/dev</code> is
limited. Additionally the container lacks a lot of kernel capabilities by default. Loading of kernel modules cannot be
done inside of the container, but rather needs to be done on the host.</p>

<h2 id="docker-requirements">Docker requirements</h2>

<p>Ranchers RKE1 (which is still the only available stable version as of the date of this post), is still using docker as
container runtime, even though this has been deprecated by the Kubernetes project. But as this is still the case, we
need to meat the docker requirements first, in order to proceed to the next step.</p>

<p>Docker requires a few kernel modules to be enabled. Those are <code class="language-plaintext highlighter-rouge">overlayfs</code> and <code class="language-plaintext highlighter-rouge">aufs</code>. We will see some other
required kernel modules later on as well, but lets keep it to those for now. Docker normally would load the modules for
us, but as this is not permitted within the LXC container, we need to do it ourself.</p>

<p>Executing following commands should do the trick.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>modprobe aufs
modprobe overlay
</code></pre></div></div>

<p>To ensure they are loaded on boot of the system the cleanest way is to create a file in <code class="language-plaintext highlighter-rouge">/etc/modules-load.d</code>.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cat &gt; /etc/modules-load.d/docker.conf &lt;&lt;EOF
aufs
overlay
EOF
</code></pre></div></div>

<p>Now let’s create a container on the proxmox host. In my case it has the id <code class="language-plaintext highlighter-rouge">100</code>, is using Ubuntu 20.04 as base image,
has <code class="language-plaintext highlighter-rouge">mgmt1.n.dev.localhost</code> as hostname. Make sure to adjust the network configuration to your network.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pct create 100 local:vztmpl/ubuntu-20.04-standard_20.04-1_amd64.tar.gz --cores 4 --memory 4096 --swap 2048 --hostname mgmt1.n.dev.localhost --rootfs local:20 --net0 name=eth0,ip=192.168.0.100/24,bridge=vmbr10,gw=192.168.0.1 --onboot 1
</code></pre></div></div>

<p>In order to run <code class="language-plaintext highlighter-rouge">docker</code> inside of the container, the container needs to be privileged. This is the case, if you don’t
especially create the containers as unprivileged in Proxmox. This alone does not give us enough permissions, we need to
enable the nesting feature in LXC as well.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pct set 100 --features nesting=1
</code></pre></div></div>

<p>Now we should be able to start the container, enter it, install <code class="language-plaintext highlighter-rouge">docker</code> and run a <code class="language-plaintext highlighter-rouge">hello-world</code> container.</p>

<p>As we don’t want the container to be accessible using ssh and only use it as docker host, we remove
some unnecessary packages. Please note that the removal of apparmor is required as well.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pct start 100
pct enter 100
apt-get -y remove openssh-server postfix accountsservice networkd-dispatcher rsyslog cron dbus apparmor
wget -O - https://releases.rancher.com/install-docker/20.10.sh | sh
reboot
</code></pre></div></div>

<p>Please note that we install docker using the script provided by Rancher, to have be compatible with the Kubernetes
version we want to install. Feel free to check the script before you just dump it into <code class="language-plaintext highlighter-rouge">sh</code>. If you don’t want to use
Kubernetes you can also install the <code class="language-plaintext highlighter-rouge">docker.io</code> package from distribution repositories.</p>

<p>Now <code class="language-plaintext highlighter-rouge">docker run hello-world</code> should give you:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>root@mgmt1:~# docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
2db29710123e: Pull complete 
Digest: sha256:4c5f3db4f8a54eb1e017c385f683a2de6e06f75be442dc32698c9bbe6c861edd
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/
</code></pre></div></div>

<h2 id="running-docker-containers-is-not-enough">Running docker containers is not enough</h2>

<p>At some point in the rancher setup, after you have created a cluster and want to add nodes to it, you are asked to
execute something like this on the node, to bootstrap the cluster.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker run -d --privileged --restart=unless-stopped --net=host -v /etc/kubernetes:/etc/kubernetes -v /var/run:/var/run  rancher/rancher-agent:v2.6.3 --server https://rancher.localhost --token &lt;some token&gt; --etcd --controlplane --worker
</code></pre></div></div>

<p>This basically creates a new container running <code class="language-plaintext highlighter-rouge">rancher-agent</code>, giving it full access to the docker daemon by mounting
<code class="language-plaintext highlighter-rouge">/var/run/docker.sock</code>. This lets <code class="language-plaintext highlighter-rouge">rancher-agent</code> start new containers with the Kubernetes processes on the node.</p>

<p>Normally you would now grab a coffee and wait 10 to 15 minutes for the node to become alive. But it’s not time for
coffee yet.</p>

<p>You will notice that the bootstrapping of the cluster now would fail. The LXC container need more capabilities, and
permissions and modules.</p>

<p>I did some research on the internet and adding a few lines to the LXC config, and a few modules should do the trick.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>modprobe ip_vs
modprobe ip_vs_rr
modprobe ip_vs_wrr
modprobe ip_vs_sh
modprobe nf_conntrack
modprobe br_netfilter
modprobe rbd
cat &gt;&gt; /etc/pve/lxc/100.conf &lt;&lt;EOF
lxc.apparmor.profile: unconfined
lxc.cgroup.devices.allow: a
lxc.cap.drop: 
lxc.mount.auto: "proc:rw sys:rw"
EOF
cat &gt;&gt; /etc/modules-load.d/docker.conf &lt;&lt;EOF
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
br_netfilter
rbd
EOF
pct stop 100
pct start 100
</code></pre></div></div>

<p>Now bootstraping fails because <code class="language-plaintext highlighter-rouge">/</code> is not shared. Ok the quick fix is to run <code class="language-plaintext highlighter-rouge">mount --make-rshared /</code> in the container.</p>

<p>But still, bootstrapping the node gives me some error like
<code class="language-plaintext highlighter-rouge">[controlPlane] Failed to upgrade Control Plane: [[host mgmt1 not ready]]</code>.</p>

<p>After running <code class="language-plaintext highlighter-rouge">docker ps</code> on the node, I noticed on container in state restarting. Looking into the logs of this
container, we notice that it did not start because <code class="language-plaintext highlighter-rouge">/dev/kmsg</code> is not available.</p>

<p>The problem seems familiar, as it was the same problem we had wen running Rancher in LXC. So I tried the same fix, we
did there.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lxc.mount.entry: /dev/kmsg dev/kmsg none defaults,bind,create=file
</code></pre></div></div>

<p>Problem seems that now <code class="language-plaintext highlighter-rouge">/dev/kmsg</code> exists, but is not readable. I did not managed to solve this problem, but found a
workaround that seems to be sufficient. Linking <code class="language-plaintext highlighter-rouge">/dev/kmsg</code> to <code class="language-plaintext highlighter-rouge">/dev/console</code>.</p>

<p>So now lets make those changes persistent. Applying those changes on boot using rc.local is not pretty, but should do
the job.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cat &gt; /etc/rc.local &lt;&lt;EOF
#!/bin/sh -e

if [ ! -e /dev/kmsg ]; then
    ln -s /dev/console /dev/kmsg
fi

mount --make-rshared /
EOF
chmod +x /etc/rc.local
/etc/rc.local
</code></pre></div></div>

<h2 id="access-to-sysctl">Access to sysctl</h2>

<p>Even after those changes, we see one container failing. Looking into it, you see that Kubernetes wants to change
<code class="language-plaintext highlighter-rouge">net.netfilter.nf_conntrack_max</code>, as the value configured by default in Proxmox is too low.</p>

<p>In my case I had to change it to at least <code class="language-plaintext highlighter-rouge">786432</code>. The strange thing is, I thought that using <code class="language-plaintext highlighter-rouge">proc:rw sys:rw</code> would
allow write access to those settings. But this seems not to be the case. Those need to be changed on the host.</p>

<p>I changed the value and tried again. Long story short, those are the settings that need to be changed:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cat &gt; /etc/sysctl.d/100-docker.conf  &lt;&lt;EOF
net.netfilter.nf_conntrack_max=786432
EOF
cat &gt;&gt; /etc/modules-load.d/docker.conf &lt;&lt;EOF
options nf_conntrack hashsize=196608
EOF
</code></pre></div></div>

<h2 id="networking-problems">Networking problems</h2>

<p>After all those changes, in my trys I was stuck at the Problem “network plugin is not ready: cni config uninitialized”.
The directory <code class="language-plaintext highlighter-rouge">/etc/cni/net.d</code> on the node (which is mapped into the containers), has not been
created. I tried all network plugins rancher provided in different versions.</p>

<p>Well, I leave it to this for now.</p>]]></content><author><name>Maximilian Ruta</name></author><category term="it" /><summary type="html"><![CDATA[About one year ago I have written an article on how to get Racher running in an LXC container on a Proxmox node. I managed to get it running and described the required steps in this article.]]></summary></entry><entry xml:lang="en"><title type="html">Rancher in LXC on Proxmox - The container matroska</title><link href="https://www.deltachaos.de//it/2021/03/10/rancher-in-lxc.html" rel="alternate" type="text/html" title="Rancher in LXC on Proxmox - The container matroska" /><published>2021-03-10T16:00:00+00:00</published><updated>2021-03-10T16:00:00+00:00</updated><id>https://www.deltachaos.de//it/2021/03/10/rancher-in-lxc</id><content type="html" xml:base="https://www.deltachaos.de//it/2021/03/10/rancher-in-lxc.html"><![CDATA[<p>As I had a lot of trouble running, rancher within a LXC container on proxmox I wanted to share my solution.</p>

<p>When rancher is started, it requires to be run in priviliged mode. It determents if has been started in priviliged mode
by checking for <code class="language-plaintext highlighter-rouge">/dev/kmsg</code> but its never mentioned. So the final soulution is, to not only create a priviliged LXC
container, but to also ensure that <code class="language-plaintext highlighter-rouge">/dev/kmsg</code> is available in the container, which is not the default.</p>

<p>For this, following entries in the container configuration on Proxmox are required:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lxc.apparmor.profile: unconfined
lxc.cap.drop:
lxc.cgroup.devices.allow: a
lxc.mount.auto: proc:rw sys:rw
lxc.mount.entry: /dev/kmsg dev/kmsg none defaults,bind,create=file
</code></pre></div></div>

<p>After you created a priviliged LXC container and added the configuration you can install docker and run rancher inside
the container.</p>]]></content><author><name>Maximilian Ruta</name></author><category term="it" /><summary type="html"><![CDATA[As I had a lot of trouble running, rancher within a LXC container on proxmox I wanted to share my solution.]]></summary></entry><entry xml:lang="en"><title type="html">The Digital Death of Journalism</title><link href="https://www.deltachaos.de//politik/2019/12/21/the-digital-death-of-journalism.html" rel="alternate" type="text/html" title="The Digital Death of Journalism" /><published>2019-12-21T09:00:00+00:00</published><updated>2019-12-21T09:00:00+00:00</updated><id>https://www.deltachaos.de//politik/2019/12/21/the-digital-death-of-journalism</id><content type="html" xml:base="https://www.deltachaos.de//politik/2019/12/21/the-digital-death-of-journalism.html"><![CDATA[<p>Political debate in Germany is becoming more and more difficult. Fake news, “alternative facts,” and one‑sided coverage
lead to an increasingly hardened discourse—and, via the nationalism that this dynamic reinforces, quite logically to a
massive crisis of multilateralism. All of this is happening at a time when the global community, facing challenges like
climate change, would need trustworthy cooperation more urgently than ever.</p>

<p>There is a medium that, out of helplessness, crawls behind paywalls into a digital depression cave—and yet reports
seriously and reliably (even if with varying emphasis). At least it still puts different perspectives side by side—just
when we need that the most. It’s called the “daily newspaper.”</p>

<h2 id="visiting-the-digital-depression-cave">Visiting the Digital Depression Cave</h2>

<p>Because I like to know different viewpoints on a topic, I follow a range of media outlets. That’s why the
Deutschlandfunk program <a href="https://www.deutschlandfunk.de/dlf-audio-archiv.2386.de.html?drau:broadcast_id=180">“Presseschau”</a>
is part of my daily routine. From taz to Handelsblatt, Süddeutsche, FAZ, and WELT—there are worlds between them in how
they interpret day‑to‑day politics. And as so often, the truth isn’t black or white, but somewhere in between.</p>

<p>Maybe comparing culture-section pieces is less interesting than comparing front pages. So: buy an entire newspaper just
for that? In the analog paper world, hardly anyone does. But digitalization could give publishers the chance to win over
regular readers of other newspapers, too.</p>

<p>But instead of shared apps, simple microtransactions, and affordable subscription models, newspapers hide behind
paywalls—and wait for death by being forgotten.</p>

<p>This kind of fragmentation is completely outdated in the age of Netflix—especially with prices of €20–€50 per month
<strong>for a single newspaper</strong>. Instead of pooling resources for a truly good app, every publisher reinvents the wheel.</p>

<h2 id="an-angry-letter">An Angry Letter</h2>

<p>All of this annoyed me so much today that I sent the following angry email to the
“Bundesverband Deutscher Zeitungsverleger e.V.” (Federal Association of German Newspaper Publishers).</p>

<blockquote>
  <p>Hello,</p>

  <p>in times of digitalization and shrinking circulation numbers, I wonder why German newspaper publishers still haven’t been able to agree on a joint digital offering at an affordable monthly subscription price.</p>

  <p>If Netflix can provide access to thousands of series and films for €10 a month, why can’t German newspaper publishers offer access to many newspaper articles for €10 a month—instead of trying to win subscribers with absurd subscription prices of €50 a month?</p>

  <p>Hiding the online offering behind paywalls achieves nothing. As a reader, I’m not willing to take out a digital subscription for an article from the “Buxtehude Remscheider Anzeiger” just because that paper happens to show up once a year in my Twitter timeline and the article looks interesting. And no, as a user I’m also not willing to click through five different pages, dig out my credit card or PayPal details, and approve a microtransaction just to unlock a single article. Then I simply won’t read it—or the person who linked it on social media will post a screenshot after 50 comments like “Paywall, can’t read it” roll in. The publisher gains nothing from that. Oh right, I forgot—there’s VG Wort for that 😂.</p>

  <p>As part of the digital generation, I can promise you one thing: this is how journalism in Germany will die. Not because the “digital generation” isn’t willing to pay for journalism, but because publishers haven’t understood how digital business models work.</p>

  <p>Best regards,
Maximilian Ruta</p>
</blockquote>

<p>If I receive a reply, I’ll publish it here as well.</p>]]></content><author><name>Maximilian Ruta</name></author><category term="politik" /><summary type="html"><![CDATA[Political debate in Germany is becoming more and more difficult. Fake news, “alternative facts,” and one‑sided coverage lead to an increasingly hardened discourse—and, via the nationalism that this dynamic reinforces, quite logically to a massive crisis of multilateralism. All of this is happening at a time when the global community, facing challenges like climate change, would need trustworthy cooperation more urgently than ever.]]></summary></entry><entry xml:lang="en"><title type="html">Why Article 13 of the EU Copyright Reform Is Disproportionate</title><link href="https://www.deltachaos.de//politik/2019/03/14/why-article-13-is-disproportionate.html" rel="alternate" type="text/html" title="Why Article 13 of the EU Copyright Reform Is Disproportionate" /><published>2019-03-14T15:00:00+00:00</published><updated>2019-03-14T15:00:00+00:00</updated><id>https://www.deltachaos.de//politik/2019/03/14/why-article-13-is-disproportionate</id><content type="html" xml:base="https://www.deltachaos.de//politik/2019/03/14/why-article-13-is-disproportionate.html"><![CDATA[<p>Today I read an email from someone who couldn’t understand why the Green Party in Cologne decided to show solidarity
with the <a href="https://savetheinternet.info">#SaveTheInternet</a> initiative. The fronts between supporters and opponents of the
planned EU copyright reform have hardened. I took this as an opportunity to explain—using an example in my reply—why I
consider Articles 13 and 11 of this directive disproportionate in their current form.</p>

<h2 id="globuli-homeopathy">Globuli (Homeopathy)</h2>

<p>It’s important not to just attack each other, but to be able to put yourself in the other side’s position. I can
absolutely understand authors and creators whose works are used constantly without proper compensation. But this reform
won’t solve that problem either. I believe we’re ultimately fighting for the same thing: fair compensation for
creators. The debate should focus on how to do this better than Article 13 proposes—instead of defending a placebo.</p>

<p>That’s what the EPP group and Mr. Voss in particular are doing. They claim the reform will strengthen creators and seem
to believe in it as firmly as some people believe in homeopathy. In fact, there are some parallels.</p>

<p>Just like in homeopathy, the idea is to fight “like with like.” YouTube earns money by using third‑party content; in
response, new enforceable rights via collecting societies would lead to blanket license agreements. Because those
licenses are flat-rate, collecting societies would then also earn money on works whose rights they don’t actually
represent. I paid €87.50 to collecting societies simply to be allowed to print contracts in my company and digitize
incoming mail.</p>

<p>And just like homeopathy, the directive is effectively powerless. The platforms that currently make lots of money with
ads—where clicking “Play” redirects you to the next porn site—platforms that don’t care about youth protection or the
existing notice-and-takedown process, will simply ignore the new rules as well.</p>

<p>Finally, this regulation—again like homeopathy—is dangerous: the many small companies that would ultimately have to
license upload filters from Google &amp; co. would end up strengthening the big players and weakening the small ones.</p>

<h2 id="an-example">An Example</h2>

<p>Back to the email I read. I replied (as one should), and I don’t want to withhold that response from anyone:</p>

<p>Bringing the legitimate interests of creators in line with new technical possibilities is always difficult. We believe
the currently proposed regulation does not do justice to either side. Since the trilogue compromise unfortunately also
removed all meaningful exemptions for small companies, the proposed measures are entirely out of proportion to their
consequences for platform operators.</p>

<p>For example, chefkoch.de would have to negotiate with all rights holders (in the world?) to license content that might
potentially be uploaded—even though the platform doesn’t really have a copyright‑infringement problem, since it’s about
recipes shared by hobby cooks. Alternatively, the platform could of course check all content for potential copyright
infringements before publication.</p>

<p>Filters could be used for this. But their development effort is far from trivial—contrary to what is suggested in this
<a href="https://www.faz.net/aktuell/feuilleton/medien/debatte-um-das-urheberrecht-der-kampf-gegen-artikel-13-16085460.html">FAZ article</a>.
Comparing this to Shazam is misleading: pattern recognition is Shazam’s core business, not a response to a regulatory
requirement. A company of that size would likely have to license the technology from providers like Google, or it would
have to review content manually with significant staffing costs. But even here, the comparison still breaks down.</p>

<p>A filter—whether human or automated—can’t actually judge whether a work infringes third‑party copyrights. It can only
compare whether something resembles a known reference. In other words: for a platform to determine that a photo of an
apple pie was taken by a different photographer than the person uploading it, the platform would first need to “know”
all apple‑pie photos taken by photographers <em>other than</em> the uploader. It should be obvious that this requirement is
simply impossible to meet.</p>

<p>Even if it were possible, you still couldn’t judge whether something is incidental inclusion (e.g. §57 UrhG) or a
quotation. Consider recording a demonstration where, for a brief moment, you can hear a snippet of a song in the
background.</p>

<p>This example shows why the consequences of the current proposal are completely disproportionate. Article 13 would at
least have to include real exemptions for companies that aren’t even the primary target of the reform.</p>

<h2 id="how-could-it-be-done-better">How Could It Be Done Better?</h2>

<p>But there are completely different proposals for protecting creators. One idea could be to skim platform profits in
favor of the creator in a notice‑and‑takedown case. And even though I personally find it irritating to have paid a flat
copyright levy for my printer—despite not committing any copyright infringements with it—that might be the kind of
compromise that could align the interests of creators with those of users.</p>

<p>Imagine if we had held manufacturers of scanners, tape recorders, cameras, computers, or printing presses liable for
copyright infringements committed with their devices. The world would look very different.</p>]]></content><author><name>Maximilian Ruta</name></author><category term="politik" /><summary type="html"><![CDATA[Today I read an email from someone who couldn’t understand why the Green Party in Cologne decided to show solidarity with the #SaveTheInternet initiative. The fronts between supporters and opponents of the planned EU copyright reform have hardened. I took this as an opportunity to explain—using an example in my reply—why I consider Articles 13 and 11 of this directive disproportionate in their current form.]]></summary></entry><entry xml:lang="en"><title type="html">How Money Becomes Civic Courage</title><link href="https://www.deltachaos.de//politik/2018/12/12/how-money-becomes-civic-courage.html" rel="alternate" type="text/html" title="How Money Becomes Civic Courage" /><published>2018-12-12T15:00:00+00:00</published><updated>2018-12-12T15:00:00+00:00</updated><id>https://www.deltachaos.de//politik/2018/12/12/how-money-becomes-civic-courage</id><content type="html" xml:base="https://www.deltachaos.de//politik/2018/12/12/how-money-becomes-civic-courage.html"><![CDATA[<p>We buy organic products, choose green electricity, and boycott companies whose political goals contradict our own
values. We accept that this may cost more. We hope this is how we can influence the world in a direction we consider
better.</p>

<p>And then there’s an industry that keeps producing new scandals: Cum-Ex, aiding tax evasion, worthless shipping funds,
opaque products. An industry that has taken on a life of its own—like an accelerant that makes new bubbles form and
burst faster and faster. The problem is that our growth-driven economic system depends on an endless supply of new
credit.</p>

<p>As consumers, we depend on cashless payments—without them, we lose access to basic necessities like housing, work, and
communication. We’ve gotten used to withdrawing cash for free almost anywhere, getting free credit cards, and paying
nothing for a checking account. Some banks even <em>pay</em> you to open an account. We feel courted—and assume banks must be
doing great business with our accounts. We assume they “speculate” with our checking balances (more accurately: demand
deposits / sight deposits) and therefore must be making enormous profits that fund all these “free” services. But all of
these services obviously cost money.</p>

<p>That’s not actually true. In reality, “free” checking accounts are often a loss for banks. Banks can only invest a small
portion of the money sitting in checking accounts—but more on that later. Still, the free account is the gateway drug:
it’s meant to get us to do more business with the bank where the bank can earn money, such as loans and credit-card
turnover, long-term investments, or a securities account.</p>

<h2 id="how-money-works">How Money Works</h2>

<p>Money acts like an advance of trust when it flows into a project as a loan or investment. It enables something to be
realized and gives it a chance.</p>

<p>That makes credit and investment powerful tools for changing the world. They decide success or failure.</p>

<p>In traditional banking, a bank can essentially only invest and lend money with maturities that match the time horizons
on which other customers can demand their money back. That’s why demand deposits aren’t particularly well-suited for
lending. Some theories (e.g. the “core deposits” concept) justify deviating from this to a degree, but that’s not the
topic here.</p>

<p>On top of that, regulations—such as capital requirements—limit the amount of credit a bank can extend.</p>

<p>So a bank can only provide long-term loans when customers invest money long-term and sufficient equity capital is
available.</p>

<h2 id="why-im-with-gls-bank">Why I’m with GLS Bank</h2>

<p>We rarely ask what this—<em>our</em>—money actually does in the world when it flows into investments and loans. It almost
certainly also finances companies, parties, and organizations whose actions would repel us if we looked closely.</p>

<p>It turns out that money can have a huge impact in changing society for the better. We want it to be used in ways that
match our values—so that companies and projects that create deeper meaning receive that advance of trust.</p>

<p>Unfortunately, it’s often hard for these projects and companies to obtain that kind of trust—and the financing that
comes with it.</p>

<p>For about two years now, I’ve been a customer and cooperative member of GLS Bank, because it mattered to me that I
wouldn’t be advocating for environmental protection, organic agriculture, fair trade, social security, the protection
of refugees, and world peace on the one hand—while my money works against those very interests on the other, simply
because my bank invests solely for maximum return.</p>

<p>GLS Bank keeps surprising me in a positive way. I’ve come to see that it doesn’t treat “fair banking” (as reviewed by
<a href="https://www.fairfinanceguide.de/">fairfinanceguide.de</a>) as a marketing tool, but actually lives those values.</p>

<p>As a cooperative bank, it belongs to its members and is run democratically. It’s a bank that
<a href="http://www.taz.de/!5507138/">doesn’t take money from Nazis</a> and that takes a stand with
<a href="https://blog.gls.de/bankspiegel/bs-2018-2-wir-sind-mehr-haltung/">#wirsindmehr</a>.</p>

<p>A bank that <a href="https://www.rbb24.de/politik/beitrag/2018/12/berlin-gls-bank-sagt-unterstuetzung-fuer-mieter-in-der-karl-marx-allee-zu.html">stands with tenants</a>
in the fight against the world’s real-estate moguls.</p>

<p>A bank that publicly supports people who are fleeing war and hardship
(<a href="https://www.gls.de/privatkunden/gls-fluechtlingshilfe/">GLS refugee aid</a>).</p>

<p>A bank that is transparent about who gets financed <a href="https://www.gls.de/media/PDF/Bankspiegel/GLS_Bankspiegel_232.pdf">(page 22)</a>
and that <a href="https://www.gls.de/privatkunden/gls-bank/gls-nachhaltigkeit/">doesn’t speculate on financial markets</a>.</p>

<p>For money to create real value and meaning, you need to understand when it can be invested long-term.</p>

<p>That doesn’t mean you must act altruistically. Of course, donated money has the longest-lasting effect because it never
needs to be repaid—and GLS Bank even offers a way to
<a href="https://www.gls.de/gemeinnuetzige-kunden/finanzieren/leih-und-schenkgemeinschaft/">finance donations</a>.
But, for example, <a href="https://www.gls.de/privatkunden/gls-anteile/">buying cooperative shares</a> also creates significant
impact: increasing the bank’s equity directly increases the amount of credit it can extend, and members receive an
annual dividend.</p>

<p>Given how much good my money can do this way, I’m happy to pay a small fee for my checking account. If this has made you
curious about GLS Bank, I recommend listening to the first episode of the GLS podcast,
<a href="https://blog.gls.de/podcast/gls-bank-podcast-folge-1/">“Who is GLS Bank?”</a>.</p>]]></content><author><name>Maximilian Ruta</name></author><category term="politik" /><summary type="html"><![CDATA[We buy organic products, choose green electricity, and boycott companies whose political goals contradict our own values. We accept that this may cost more. We hope this is how we can influence the world in a direction we consider better.]]></summary></entry></feed>