<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <generator uri="http://jekyllrb.com" version="4.4.1">Jekyll</generator>
  <link href="https://blog.ganneff.de/atom.xml/atom.xml" rel="self" type="application/atom+xml" />
  <link href="https://blog.ganneff.de/" rel="alternate" type="text/html" />
  <updated>2026-04-03T15:23:10+02:00</updated>
  <id>https://blog.ganneff.de/</id>
    <title>Ganneff&apos;s Little Blog</title>
    <subtitle>Thoughts of a small and very unimportant Debian Developer</subtitle>
    <author>
        <name>Joerg Jaspert</name>
        <email>joerg@ganneff.de</email>
        <uri>https://blog.ganneff.de/</uri>
    </author>
  
    <entry>
      <title>Building a house - 1 year in</title>
      <link href="https://blog.ganneff.de/2026/04/house.html" rel="alternate" type="text/html" title="Building a house - 1 year in" />
      <published>2026-04-02T23:23:23+02:00</published>
       <updated>2026-04-02T23:23:23+02:00</updated>
      <id>https://blog.ganneff.de/2026/04/house</id>
      <content type="html" xml:base="https://blog.ganneff.de/2026/04/house.html">&lt;p&gt;Haven’t written here about it, but last March we finally started on
our journey to get our own house build, so we can move out of the
rented flat here.&lt;/p&gt;

&lt;p&gt;That will be a big step, both the actual building, but also the
moving - I am living at this one single place for 36 years now.&lt;/p&gt;

&lt;p&gt;If you can read german there is &lt;a href=&quot;https://haus.ganneff.de/&quot;&gt;a dedicated
webpage&lt;/a&gt; where I sometimes write about the
process. Will have much more details (and way more ramblings) than the
following part.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you can’t read german, a somewhat short summary follows&lt;/strong&gt;. Yes,
still a lot of text, but shortened, still.&lt;/p&gt;

&lt;h3 id=&quot;what-why-now&quot;&gt;What? Why now?&lt;/h3&gt;
&lt;p&gt;Current flat has 83m² - which simply isn’t enough space. And
the number of rooms also doesn’t fit anymore. But it is hard to find a
place that fits our requirements (which do include location).&lt;/p&gt;

&lt;p&gt;Moving to a different rented place would also mean changed amount of
rent. And nowadays that would be huge increase (my current rent is
still the price from about 30 years ago!).&lt;/p&gt;

&lt;p&gt;So if we go and pay more - we could adjust and pay for something we
own instead. And both, my wife and I had changes in our jobs that made
it possible for us now, so we started looking.&lt;/p&gt;

&lt;h3 id=&quot;market&quot;&gt;Market&lt;/h3&gt;
&lt;p&gt;Brrrr, looking is good, actually finding something that fits - not so.
We never found an offer that fit. Space wise, sure. But then location
was off, or price was idiotically high. Location fit, but then size
was a joke, and guess about the price… Who needs 200 square meters
with 3 rooms? Entirely stupid design choices there. Or how about 40
square meters of hallway - with 50m² of tiny rooms around. What are
they smoking? Oh, there, useful size, good rooms - but now you want
more money than a kidney is worth, or something. Thanks, no.&lt;/p&gt;

&lt;h3 id=&quot;new-place&quot;&gt;New place&lt;/h3&gt;
&lt;p&gt;In February 2025 we finally got lucky and found a (newly opened) area
with a large number of places to build a house on. Had multiple talks
with someone from on of the companies developing that area (there are
two you can select from), then talked with banks and signed a contract
in March 2025. We got promised that actual house construction would be
first quarter of 2026, finished in second quarter.&lt;/p&gt;

&lt;h3 id=&quot;house-type&quot;&gt;House type&lt;/h3&gt;
&lt;p&gt;There are basically 2 ways of building a new house (that matter here).
First is called “Massivhaus”, second is called “Fertighaus” in german,
roughly translating to solid and prefabricated. The latter commonly a
wood based construction, though it doesn’t need to be. The important
part of it is the prefabrication, walls and stuff get assembled in a
factory somewhere and then transported to your place, where they play
“big kid lego” for a day and suddenly a house is there.&lt;/p&gt;

&lt;p&gt;A common thought is “prefabricated” is faster, but that is only a half
true. Sure, the actual work on side is way shorter - usually one or
two days and the house is done - while a massive construction usually
takes weeks to build up. But that is only a tiny part of the time
needed, the major part goes of into planning and waiting and in there
it doesn’t matter what material you end up with.&lt;/p&gt;

&lt;h2 id=&quot;money-fun&quot;&gt;Money fun&lt;/h2&gt;
&lt;p&gt;Last year already wasn’t the best time to start a huge loan - but
isn’t it always “&lt;em&gt;a few years ago would have been better&lt;/em&gt;”? So we had
multiple talks with different banks and specialised consultants until
we found something that we thought is good for us.&lt;/p&gt;

&lt;p&gt;Thinking about it now - we should have put even more money on top as
“reserve”, but who could have thought that 2026 turns into such a
shitshow? Does not help at all, quite the contrary. And that damn
lotto game always ends up with the wrong numbers, meh.&lt;/p&gt;

&lt;h1 id=&quot;plans-and-plans-and-more-plans---and-rules&quot;&gt;Plans and plans and more plans - and rules&lt;/h1&gt;
&lt;p&gt;For whichever reason you can not just go and put something on your
ground and be happy. At least not if you are part of the normal people and not
enormously rich. There is a large set of rules to follow. Usually that
is a good thing, even though some rules are sometimes hard to understand.&lt;/p&gt;

&lt;p&gt;In Germany, besides the usual laws, we have something that is called
“Bebauungsplan”, which translates to “development plan” (don’t know if
that carries the right meaning, it’s a plan on what and how may be
build, which can have really detailed specifications in). It basically
tells you every aspect &lt;em&gt;on top&lt;/em&gt; of the normal law that you have to
keep in mind.&lt;/p&gt;

&lt;p&gt;In our case we have the requirement of 2 full floors and CAN have a
third smaller on top, it limits how high the house can be &lt;em&gt;and&lt;/em&gt; also
how high our ground floor may be compared to the street. It regulates
where on the property we may build and how much ground we may cover
with the house, it gives a set of colors we are allowed to use, it
demands a flat roof that we must have as a green roof and has a number
of things more that aren’t important enough to list here. If you do
want to see the full list, &lt;a href=&quot;https://haus.ganneff.de/baustellen/2025/03/bebauungsplan/&quot;&gt;my german post on it has all the details
that matter to
us&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With all that stuff in mind - off to plans. Wouldn’t have believed how
many details there are to take in. Room sizes are simple, but how to
arrange them for ideal usage of the sun, useful ways inside the house,
but also keeping in mind that water needs to flow through and out.
Putting a bath room right atop a living room means a water pipe needs
to go down there. Switch the bath room side in the house, and it
suddenly is above the kitchen - means you can connect the pipes from
it to the ones from kitchen, which is much preferred than going
through the living room. And lots more such things.&lt;/p&gt;

&lt;p&gt;It took us until nearly end of October to finalize the plans! And we
learned a whole load from it. We started with a lot of wishes. The
planner tried to make them work. Then we changed our minds. Plans
changed. Minds changed again. Comparing the end result with the first
draft we changed most of the ground floor around, with only the stairs
and the entrance door at the same position. Less changes for the upper
floor, but still enough.&lt;/p&gt;

&lt;h1 id=&quot;side-quests&quot;&gt;Side quests&lt;/h1&gt;
&lt;p&gt;The whole year was riddled with something my son named side quests. We
visited a construction exhibition near us, we went to the house
builders factory and took a look on how they work. We went to many
different other companies that do SOME type of work which we need
soon, say inside floors, painters, kitchen and more stuff.&lt;/p&gt;

&lt;p&gt;Of course the most important side quest was a visit to the notary to
finalize the contracts, especially for the plot of land (in Germany
you must have a notary for that to get entered into the governments
books). Creates lots of fees, of course, for the notary and also the
government (both fees and taxes here).&lt;/p&gt;

&lt;h1 id=&quot;building-permit&quot;&gt;Building permit&lt;/h1&gt;
&lt;p&gt;We had been lucky and only needed a small change to the plans to get
the building permit - and the second part, the wastewater permit (yes,
you need a separate one for this) also got through without trouble.&lt;/p&gt;

&lt;h1 id=&quot;choices-so-many-of-them&quot;&gt;Choices, so many of them&lt;/h1&gt;
&lt;p&gt;So in January we finally had an appointment for something that’s
called “Bemusterung” which badly translates to “Sampling”. Basically
two days at the house builders factory to select all of what’s needed
for the house that you don’t do in the plans. Doors, inside and out
and their type and color and handles. Same things for the windows and
the blinds and the protection level you want the windows to have.
Decide about stairs, design for the sanitary installations - and also
the height of the toilet! - and the tiles to put into the bathrooms.
Decisions on all the tech needed (heating system, ventilation and
whatnot.&lt;/p&gt;

&lt;p&gt;Two days, busy ones - and you can easily spend a lot of extra money
here if you aren’t careful. We managed to get “out of it” with only
about 4000€ extra, so pretty good.&lt;/p&gt;

&lt;h1 id=&quot;electro-and-automation&quot;&gt;Electro and automation&lt;/h1&gt;
&lt;p&gt;Now, here I am special. Back when I was young the job I learned is
electrician. So here I have very detailed wishes. I am also running
lots of automatism in my current flat - obviously the new house should
be better than that. So I have a lot of ideas and thoughts on it, so
this is entirely extra and certainly out of the ordinary the house
builder usually see.&lt;/p&gt;

&lt;p&gt;Which means I do all of that on my own. Well, the planning and some of
the work, I must have a company at hand for certain tasks, it is
required by some rules. But they will do what I planned, as long as I
don’t violate regulations.&lt;/p&gt;

&lt;p&gt;Which means the whole electrical installation is … different.
Entirely planned for automatisms and using KNX for it. I am so happy
to ditch Homeassistant and the load of Homematic, Zigbee and ZWave
based wireless things.&lt;/p&gt;

&lt;p&gt;Ok, Homeassistant is a nice thing - it can do a lot. And it can bridge
between about any system you can find. But it is a central single point of
failure. And it is a system that needs constant maintenance. Not
touched for a while? Plan for a few hours playing update whack-a-mole.
And often enough a component here or there breaks with an update. Can
be fixed, but takes another hour or two.&lt;/p&gt;

&lt;p&gt;So I change. Away from wireless based stuff. To wires. To a system
thats a standard for decades already. And works entirely without a
SPOF. (Yes, you can add one here too). And, most important, should I
ever die - can easily be maintained by anyone out there dealing with
KNX, which is a large number of people and companies. Without digging
through dozens of specialised integrations and whatnot.&lt;/p&gt;

&lt;p&gt;I may even end up with Homeassistant again - but that will entirely be
as a client. It won’t drive automations. It won’t be the central point
to do anything for the house. It will be a logging and data collecting
thing that enables me to put up easy visualizations. It may be an easy
interface for smartphones or tablets to control parts of the house,
for those parts where one wants this to happen. Not the usual
day-to-day stuff, extras on top.&lt;/p&gt;

&lt;h1 id=&quot;actual-work-happening&quot;&gt;Actual work happening&lt;/h1&gt;
&lt;p&gt;Since march there &lt;em&gt;finally&lt;/em&gt; is action visible. The base of the house
is getting build. Wednesday the 1st April we finally got the base
slab poured on the construction site and in another 10 days the house
is getting delivered and build up. A 40ton mobile crane will be there.&lt;/p&gt;
</content>
      
      
      
        <category term="house" />
      
        <category term="work" />
      
      
        <summary>Haven’t written here about it, but last March we finally started onour journey to get our own house build, so we can move out of therented flat here.</summary>
      
    </entry>
  
    <entry>
      <title>AI Shit, go away; iocaine to the rescue</title>
      <link href="https://blog.ganneff.de/2026/01/ai-slop.html" rel="alternate" type="text/html" title="AI Shit, go away; iocaine to the rescue" />
      <published>2026-01-03T14:23:42+01:00</published>
       <updated>2026-01-03T14:23:42+01:00</updated>
      <id>https://blog.ganneff.de/2026/01/ai-slop</id>
      <content type="html" xml:base="https://blog.ganneff.de/2026/01/ai-slop.html">&lt;p&gt;As a lot of people do, I have some content that is reachable using
webbrowsers. There is the password manager
&lt;a href=&quot;https://github.com/dani-garcia/vaultwarden&quot;&gt;Vaultwarden&lt;/a&gt;, an instance
of &lt;a href=&quot;https://immich.app/&quot;&gt;Immich&lt;/a&gt;, &lt;a href=&quot;https://forgejo.org/&quot;&gt;ForgeJo&lt;/a&gt; for
some personal git repos, my blog and some other random pages here and
there.&lt;/p&gt;

&lt;p&gt;All of this never had been a problem, running a webserver is a
relatively simple task, no matter if you use &lt;a href=&quot;https://packages.debian.org/apache2 &quot;&gt;apache2 &lt;/a&gt;, &lt;a href=&quot;https://packages.debian.org/nginx &quot;&gt;nginx &lt;/a&gt; or any of the other possibilities. And the things
mentioned above bring their own daemon to serve the users.&lt;/p&gt;

&lt;h1 id=&quot;ai-crap&quot;&gt;AI crap&lt;/h1&gt;
&lt;p&gt;And then some idiot somewhere had the idea to ignore every law, every
copyright and every normal behaviour and run some shit AI bot. And
more idiots followed. And now we have more AI bots than humans
generating traffic.&lt;/p&gt;

&lt;p&gt;And those AI shit crawlers do not respect any limits. robots.txt, slow
servers, anything to keep your meager little site up and alive? Them
idiots throw more resources onto them to steal content. No sense at
all.&lt;/p&gt;

&lt;h1 id=&quot;iocaine-to-the-rescue&quot;&gt;iocaine to the rescue&lt;/h1&gt;
&lt;p&gt;So them AI bros want to ignore everything and just fetch the whole
internet? Without any consideration if thats even wanted? Or legal?
There are people who dislike this. I am one of them, but there are
some who got annoyed enough to develop tools to fight the AI
craziness. One of those tools is
&lt;a href=&quot;https://iocaine.madhouse-project.org/&quot;&gt;iocaine&lt;/a&gt; - it says about
itself that it is &lt;strong&gt;The deadliest poison known to AI&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;feed-ai-bots-sht&quot;&gt;Feed AI bots sh*t&lt;/h2&gt;
&lt;p&gt;So you want content? You do not accept any &lt;em&gt;Go away&lt;/em&gt;? Then here is
content. It is crap, but appearently you don’t care. So have fun.&lt;/p&gt;

&lt;p&gt;What iocaine does is (cite from their webpage) &lt;em&gt;“not made for making
the Crawlers go away. It is an aggressive defense mechanism that tries
its best to take the blunt of the assault, serve them garbage, and
keep them off of upstream resources”&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;That is, instead of the expensive webapp using a lot of resources that
are basically wasted for nothing, iocaine generates a small static
page (with some links back to itself, so the crawler shit stays
happy). Which takes a hell of a lot less resource than any fullblown
app.&lt;/p&gt;

&lt;h1 id=&quot;iocaine-setup&quot;&gt;iocaine setup&lt;/h1&gt;
&lt;p&gt;The website has a
&lt;a href=&quot;https://iocaine.madhouse-project.org/documentation/&quot;&gt;good Documentation&lt;/a&gt;, it is not hard to setup. Still, I had to adjust some
things for my setup, as I use &lt;a href=&quot;[https://github.com/lucaslorentz/caddy-docker-proxy&quot;&gt;Caddy Docker Proxy&lt;/a&gt; nowadays
and wanted to keep the config within the docker setup, that is, within
the labels.&lt;/p&gt;

&lt;h2 id=&quot;caddy-container&quot;&gt;Caddy container&lt;/h2&gt;
&lt;p&gt;So my container setup for the caddy itself contains the following
extra lines:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;    &lt;span class=&quot;na&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;caddy_0.email&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;email@example.com&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;caddy_1&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;(iocaine)&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;caddy_1.0_@read&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;method GET HEAD&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;caddy_1.1_reverse_proxy&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;@read&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;iocaine:42069&quot;&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;caddy_1.1_reverse_proxy.@fallback&quot;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;421&quot;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;caddy_1.1_reverse_proxy.handle_response&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;@fallback&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This will be translated to the following Caddy config snippet:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-conf&quot; data-lang=&quot;conf&quot;&gt;(&lt;span class=&quot;n&quot;&gt;iocaine&lt;/span&gt;) {
        @&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GET&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HEAD&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;reverse_proxy&lt;/span&gt; @&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iocaine&lt;/span&gt;:&lt;span class=&quot;m&quot;&gt;42069&lt;/span&gt; {
                @&lt;span class=&quot;n&quot;&gt;fallback&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;status&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;421&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;handle_response&lt;/span&gt; @&lt;span class=&quot;n&quot;&gt;fallback&lt;/span&gt;
        }
}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;any-container-that-should-be-protected-by-iocaine&quot;&gt;Any container that should be protected by iocaine&lt;/h2&gt;
&lt;p&gt;All the containers that are “behind” the Caddy reverse proxy can now
get protected by iocaine with just one more line in their
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-compose.yaml&lt;/code&gt;. So now we have&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;   &lt;span class=&quot;na&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;caddy&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;service.example.com&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;caddy.reverse_proxy&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;{{upstreams&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;3000}}&quot;&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;caddy.import&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;iocaine&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;which translates to&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-conf&quot; data-lang=&quot;conf&quot;&gt;&lt;span class=&quot;n&quot;&gt;service&lt;/span&gt;.&lt;span class=&quot;n&quot;&gt;example&lt;/span&gt;.&lt;span class=&quot;n&quot;&gt;com&lt;/span&gt; {
        &lt;span class=&quot;n&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iocaine&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;reverse_proxy&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;172&lt;/span&gt;.&lt;span class=&quot;m&quot;&gt;18&lt;/span&gt;.&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;.&lt;span class=&quot;m&quot;&gt;6&lt;/span&gt;:&lt;span class=&quot;m&quot;&gt;3000&lt;/span&gt;
}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So with one simple extra label for the docker container I have iocaine
activated.&lt;/p&gt;

&lt;h1 id=&quot;result-byebye-most-ai-bots&quot;&gt;Result? ByeBye (most) AI Bots&lt;/h1&gt;
&lt;p&gt;Looking at the services that got hammered most from those crap bots -
deploying this iocaine container and telling Caddy about it solved the
problem for me. 98% of the requests from the bots now go to iocaine
and no longer hog resources in the actual services.&lt;/p&gt;

&lt;p&gt;I wish it wouldn’t be neccessary to run such tools. But as long as we
have shitheads doing the AI hype there is no hope. I wish they all
would end up in Jail for all their various stealing they do. And
someone with a little more brain left would set things up sensibly,
then the AI thing could maybe turn out something good and useful.&lt;/p&gt;

&lt;p&gt;But currently it is all crap.&lt;/p&gt;
</content>
      
      
      
        <category term="ai" />
      
        <category term="iocaine" />
      
        <category term="debian" />
      
      
        <summary>As a lot of people do, I have some content that is reachable usingwebbrowsers. There is the password managerVaultwarden, an instanceof Immich, ForgeJo forsome personal git repos, my blog and some other random pages here andthere.</summary>
      
    </entry>
  
    <entry>
      <title>Electric Car, Vacation trip</title>
      <link href="https://blog.ganneff.de/2024/08/electric-car.html" rel="alternate" type="text/html" title="Electric Car, Vacation trip" />
      <published>2024-08-15T12:12:15+02:00</published>
       <updated>2024-08-15T12:12:15+02:00</updated>
      <id>https://blog.ganneff.de/2024/08/electric-car</id>
      <content type="html" xml:base="https://blog.ganneff.de/2024/08/electric-car.html">&lt;h2 id=&quot;electric-car&quot;&gt;Electric Car&lt;/h2&gt;
&lt;p&gt;A while ago I got my hands on an electric car - after not having owned
a car for most of my life (there really is not much need here). It
wasn’t planned nor a goal of mine, but it kind of “came out of talks
with my boss”, so now it’s there.&lt;/p&gt;

&lt;p&gt;Due to some special rules in the german tax system it turns out
&lt;strong&gt;really&lt;/strong&gt; cheap for me - it comes from the company, which allows
personal use. So I have to pay taxes on the value of it plus whichever
amount of kilometers I have to drive to work. And the latter is what
is good for me - I have homeoffice in my contract, so no drive to
work, except maybe once a year for something. So no regular trip to
calculate, only if I ever really have to do a trip to the office.&lt;/p&gt;

&lt;p&gt;And it being an electric car, running costs are also cheap. &lt;strong&gt;Way&lt;/strong&gt;
below the outdated tech that needs gas to run, is annoyingly loud and
stinks.&lt;/p&gt;

&lt;h3 id=&quot;the-car&quot;&gt;The car&lt;/h3&gt;
&lt;p&gt;In the past I used either car sharing or renting a car when I needed
one, depending on what I actually needed. Last times renting I already
tried electric variants, so I could compare this with.&lt;/p&gt;

&lt;p&gt;What I have now is a “Citroen e-Berlingo XL” from 2023 (so not the latest
change from 2024), which is on the &lt;strong&gt;huge&lt;/strong&gt; size for space, but small
for battery. It has 7 seats (though I have the last 2 currently taken
out, no daily need) and more storage space than I need even on a
vacation trip.&lt;/p&gt;

&lt;p&gt;The engine (or well, it’s battery) is on the small side - a capacity
of 50 kWh means it only has 278km reach according to WLTP. That
actually is a good bit less - as usual, those numbers are lying for
the producer. Turns out that on highways in a more realistic mode than
WLTP (read: real driving) it’s somewhat around 120km before one wants a
charger again. But, looking around, at least in Germany that is not a
big problem, there are more than enough chargers available.&lt;/p&gt;

&lt;h4 id=&quot;driving&quot;&gt;Driving&lt;/h4&gt;
&lt;p&gt;Actually driving experience is good. It sure is a huge car (4.7m long,
1.85m high/wide) and feels more like driving a (small) bus, but it is
easy to handle. Maximum speed is limited (or the small battery would
suck even more) to 135km/h, but that is more than enough. Even on
german highways. Did my vacation trip with cruise control set to
115km/h and very few times only went above that manually. Real relaxed
driving that was.&lt;/p&gt;

&lt;h2 id=&quot;vacation-trip&quot;&gt;Vacation trip&lt;/h2&gt;
&lt;p&gt;So we had a vacation just recently, and instead of renting a car for
the trip we, of course, wanted to take the e-Berlingo. Distance was
about double what the car can (realistically!) do, so one charging
stop in the middle somewhere was a &lt;strong&gt;must&lt;/strong&gt;. Not having had to charge
on highways yet - and entirely new with this car - that made for a bit of
nervousness, but it all turned out really good. There are really nice
tools like &lt;a href=&quot;https://abetterrouteplanner.com/&quot;&gt;ABRP&lt;/a&gt; to plan your trip
including charging, which can take live data of availability of
charging points into the planning.&lt;/p&gt;

&lt;p&gt;And it turned out nice - we reached our planned charging point and
found a &lt;strong&gt;long&lt;/strong&gt; queue of cars waiting. But turns out it was all those
poor folks that need actual gasoline for their outdated combustion
engines. The charging points for EV cars still had enough free space,
so we could bypass the queue and directly start charging. We also did
not need to repark the car after just a few minutes, we could directly
start our break.&lt;/p&gt;

&lt;p&gt;With a charging time of approx. 30 minutes using the fast charger,
such a break is long enough to get enough energy for the next part of
the trip and short enough to not be annoying.&lt;/p&gt;

&lt;h2 id=&quot;charging-prices&quot;&gt;Charging prices&lt;/h2&gt;
&lt;p&gt;At home it depends. If one has some photovoltaic system to get power,
charging is basically free. If not it depends on whichever contract
one has, costs will be somewhat between 0 and ~30cent per kWh. Not
much, and way below gasoline costs.&lt;/p&gt;

&lt;p&gt;Outside, using a fast charger, prices vary depending on where you
charge - and with what charging card. Prices between 40 and 70cent /
kWh, and the same charging point can vary, just from the card one
uses. That is a thing that the EU could actually go and better
regulate, similar to the phone regulations it took. Still, the costs
are still way below gasoline.&lt;/p&gt;

&lt;h3 id=&quot;charging-cards&quot;&gt;Charging cards&lt;/h3&gt;
&lt;p&gt;There is a huge amount of different providers available, and all do
their own things in pricing and how one can use them. They do have
standards (say, the plugs are standardized, by now the way to start
charging also), and that enables roaming (use a charging card of one
provider at a charging point of another), but other than that, it
seems to be random.&lt;/p&gt;

&lt;p&gt;That is - if you use card A on a charging point of Provider B you may
pay 0.49cents, if you use card C on the same point, it may charge you
0.79cents. And card D isn’t taken at all. Some (the newer ones) you
can pay directly by credit card, many you can’t. Some may allow paypal
or Google/Apple Pay. So in the end you need more than just one
charging card - I collected 8 free ones by now - just to be sure you
can find a combination that isn’t hugely overpriced.&lt;/p&gt;
</content>
      
      
      
        <category term="ev" />
      
        <category term="electric" />
      
        <category term="car" />
      
        <category term="vacation" />
      
      
        <summary>Electric CarA while ago I got my hands on an electric car - after not having owneda car for most of my life (there really is not much need here). Itwasn’t planned nor a goal of mine, but it kind of “came out of talkswith my boss”, so now it’s there.</summary>
      
    </entry>
  
    <entry>
      <title>From QNAP QTS to TrueNAS Scale</title>
      <link href="https://blog.ganneff.de/2022/11/from-qnap-qts-to-truenas-scale.html" rel="alternate" type="text/html" title="From QNAP QTS to TrueNAS Scale" />
      <published>2022-11-19T13:20:33+01:00</published>
       <updated>2022-11-19T13:20:33+01:00</updated>
      <id>https://blog.ganneff.de/2022/11/from-qnap-qts-to-truenas-scale</id>
      <content type="html" xml:base="https://blog.ganneff.de/2022/11/from-qnap-qts-to-truenas-scale.html">&lt;h1 id=&quot;history-setup&quot;&gt;History, Setup&lt;/h1&gt;
&lt;p&gt;So for quite some time I have a QNAP TS-873x here, equipped with 8
Western Digital Red 10 TB disks, plus 2 WD Blue 500G M2 SSDs. The QNAP
itself has an “AMD Embedded R-Series RX-421MD” with 4 cores and was
equipped with 48G RAM.&lt;/p&gt;

&lt;p&gt;Initially I had been quite happy, the system is nice. It was fast, it
was easy to get to run and the setup of things I wanted was simple
enough. All in a web interface that tries to imitate a kind of
workstation feeling and also tries to hide that it is actually a
webinterface.&lt;/p&gt;

&lt;p&gt;Natually with that amount of disks I had a RAID6 for the disks, plus
RAID1 for the SSDs. And then configured as a big storage pool with the
RAID1 as cache. Below the hood QNAP uses MDADM Raid and LVM (if you
want, with thin provisioning), in some form of emdedded linux. The
interface allows for regular snapshots of your storage with flexible
enough schedules to create them, so it all appears pretty good.&lt;/p&gt;

&lt;h1 id=&quot;qnap-slow&quot;&gt;QNAP slow&lt;/h1&gt;
&lt;p&gt;Fast forward some time and it gets annoying. First off you really
should have regular raid resyncs scheduled, and while you can set
priorities on them and have them low priority, they make the whole
system feel very sluggish, quite annoying. And sure, power failure
(rare, but can happen) means another full resync run. Also, it appears
all of the snapshots are always mounted to some
/mnt/snapshot/something place (df on the system gets quite unusable).&lt;/p&gt;

&lt;p&gt;Second, the reboot times. QNAP seems to be affected by the “more
features, fuck performance” virus, and bloat their OS with more and
more features while completly ignoring the performance. Everytime they
do an “upgrade” it feels worse. Lately reboot times went up to 10 to
15 minutes - and then it still hadn’t started the virtual machines /
docker containers one might run on. Another 5 to 10 minutes for those.
Opening the file explorer - ages on calculating what to show. Trying
to get the storage setup shown? Go get a coffee, but please fetch the
beans directly from the plantation, or you are too fast.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Annoying&lt;/em&gt; it was. And no, no broken disks or fan or anything, it all
checks out fine.&lt;/p&gt;

&lt;h1 id=&quot;replace-qnaps-qts-system&quot;&gt;Replace QNAPs QTS system&lt;/h1&gt;
&lt;p&gt;So I started looking around what to do. More RAM may help a little
bit, but I already had 48G, the system itself appears to only do 64G
maximum, so not much chance of it helping enough. Hardware is all fine
and working, so software needs to be changed. Sounds hard, but turns
out, it is not.&lt;/p&gt;

&lt;h1 id=&quot;truenas&quot;&gt;TrueNAS&lt;/h1&gt;
&lt;p&gt;And I found that multiple people replaced the QNAPs own system with a
TrueNAS installation and generally had been happy. Looking further I
found that TrueNAS has a variant called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Scale&lt;/code&gt; - which is based on
Debian. Doubly good, that, so I went off checking what I may need for
it.&lt;/p&gt;

&lt;h2 id=&quot;requirements&quot;&gt;Requirements&lt;/h2&gt;
&lt;p&gt;Heck, that was a step back. To install TrueNAS you need an HDMI out
and a disk to put it on. The one that QTS uses is too small, so no
option.&lt;/p&gt;

&lt;figure class=&quot;center&quot;&gt;
  &lt;a href=&quot;/assets/images/fullsize/2022/20221114_qnapdisk.jpg&quot; title=&quot;Original/Fullsize image&quot;&gt;
&lt;img src=&quot;/assets/images/resized/2022/20221114_qnapdisk.jpg-32f3ed4/320x346.jpg&quot; srcset=&quot;/assets/images/resized/2022/20221114_qnapdisk.jpg-32f3ed4/1024x1107.jpg 1024w, /assets/images/resized/2022/20221114_qnapdisk.jpg-32f3ed4/512x553.jpg 512w, /assets/images/resized/2022/20221114_qnapdisk.jpg-32f3ed4/1089x1177.jpg 1089w, /assets/images/resized/2022/20221114_qnapdisk.jpg-32f3ed4/640x692.jpg 640w, /assets/images/resized/2022/20221114_qnapdisk.jpg-32f3ed4/320x346.jpg 320w&quot; sizes=&quot;(min-width: 400px) 512px, (min-width: 900px) 1024px, 100vw&quot; alt=&quot;QNAPs
 internal USB disk&quot; class=&quot;center&quot; width=&quot;400&quot; /&gt;

  
    &lt;figcaption&gt;
      QNAPs original internal
 USB drive, DOM
    &lt;/figcaption&gt;
  
  &lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;So either use one of the SSDs that played cache (and
should do so again in TrueNAS, or get the QNAP original replaced.&lt;/p&gt;

&lt;p&gt;HDMI out is simple, get a cheap card and put it into one of the two
PCIe-4x slots, done. The disk thing looked more complicated, as QNAP
uses some “internal usb stick thing”. Turns out it is “just” a USB
stick that has an 8+1pin connector. Couldn’t find anything nice as
replacement, but hey, there are 9-pin to USB-A adapters.&lt;/p&gt;

&lt;figure class=&quot;center&quot;&gt;
  &lt;a href=&quot;/assets/images/fullsize/2022/9pinusba.jpg&quot; title=&quot;Original/Fullsize image&quot;&gt;
&lt;img src=&quot;/assets/images/resized/2022/9pinusba.jpg-457fc09/320x534.jpg&quot; srcset=&quot;/assets/images/resized/2022/9pinusba.jpg-457fc09/550x917.jpg 550w, /assets/images/resized/2022/9pinusba.jpg-457fc09/512x854.jpg 512w, /assets/images/resized/2022/9pinusba.jpg-457fc09/320x534.jpg 320w&quot; sizes=&quot;(min-width: 400px) 512px, (min-width: 900px) 1024px, 100vw&quot; alt=&quot;9PIN to USB A&quot; class=&quot;center&quot; width=&quot;400&quot; /&gt;

  
    &lt;figcaption&gt;
      a 9pin to USB A adapter
    &lt;/figcaption&gt;
  
  &lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;With that adapter, one can take some random M2 SSD and an M2-to-USB
case, plus some cabling, and voila, we have a nice system disk.&lt;/p&gt;

&lt;figure class=&quot;center&quot;&gt;
  &lt;a href=&quot;/assets/images/fullsize/2022/20221113_cable1.jpg&quot; title=&quot;Original/Fullsize image&quot;&gt;
&lt;img src=&quot;/assets/images/resized/2022/20221113_cable1.jpg-8839514/320x591.jpg&quot; srcset=&quot;/assets/images/resized/2022/20221113_cable1.jpg-8839514/360x665.jpg 360w, /assets/images/resized/2022/20221113_cable1.jpg-8839514/320x591.jpg 320w&quot; sizes=&quot;(min-width: 400px) 512px, (min-width: 900px) 1024px, 100vw&quot; alt=&quot;USB 9pin
 to USB-A cable connected to Motherboard and some more cable&quot; class=&quot;center&quot; width=&quot;400&quot; /&gt;

  
    &lt;figcaption&gt;
      9pin adapter to USB-A connected with some
 more cable
    &lt;/figcaption&gt;
  
  &lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;Obviously there isn’t a good place to put this SSD case and cable, but the
QNAP case is large enough to find space and use some cable ties to store it
safely. Space enough to get the cable from the side, where the
mainboard is to the place I mounted it, so all fine.&lt;/p&gt;

&lt;figure class=&quot;center&quot;&gt;
  &lt;a href=&quot;/assets/images/fullsize/2022/20221113_mounted.jpg&quot; title=&quot;Original/Fullsize image&quot;&gt;
&lt;img src=&quot;/assets/images/resized/2022/20221113_mounted.jpg-1b95100/320x202.jpg&quot; srcset=&quot;/assets/images/resized/2022/20221113_mounted.jpg-1b95100/570x360.jpg 570w, /assets/images/resized/2022/20221113_mounted.jpg-1b95100/512x323.jpg 512w, /assets/images/resized/2022/20221113_mounted.jpg-1b95100/320x202.jpg 320w&quot; sizes=&quot;(min-width: 400px) 512px, (min-width: 900px) 1024px, 100vw&quot; alt=&quot;Mounted
 SSD in external case, also shows the video card&quot; class=&quot;center&quot; width=&quot;400&quot; /&gt;

  
    &lt;figcaption&gt;
      Mounted SSD in its external case
    &lt;/figcaption&gt;
  
  &lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;The next best M2 SSD was a Western Digital Red with 500G - and while
this is WAY too much for TrueNAS, it works. And hey, only using a tiny
fraction? Oh so much more cells available internally to use when
others break. Or something…&lt;/p&gt;

&lt;p&gt;Together with the Asus card mounted I was able to install TrueNAS.
Which is simple, their installer is easy enough to follow, just make
sure to select the right disk to put it on.&lt;/p&gt;

&lt;h3 id=&quot;preserving-data-during-the-move&quot;&gt;Preserving data during the move&lt;/h3&gt;
&lt;p&gt;Switching from QNAP QTS to TrueNAS Scale means changing from MDADM
Raid with LVM and ext4 on top to ZFS and as such all data on it gets
erased. So a backup first is helpful, and I got myself two external
Seagate USB Disks of 6TB each - enough for the data I wanted to keep.&lt;/p&gt;

&lt;p&gt;Copying things all over took ages, especially as the QNAP backup
thingie sucks, it was breaking quite often. Also, for some reason I
did not investigate, the performance of it was real bad. It started at
a maximum of 50MB/s, but the last terabyte of data was copied
at MUCH less than that, and so it took much longer than I anticipated.&lt;/p&gt;

&lt;p&gt;Copying back was slow too, but much less so. Of course reading things
usually is faster than writing, with it going around 100MB/s most of
the time, which is quite a bit more - still not what USB3 can actually
do, but I guess the AMD chip doesn’t want to go that fast.&lt;/p&gt;

&lt;h1 id=&quot;truenas-experience&quot;&gt;TrueNAS experience&lt;/h1&gt;
&lt;p&gt;The installation went mostly smooth, the only real trouble had been on
my side. Turns out that a bad network cable does NOT help the network
setup, who would have thought. Other than that it is the usual set of
questions you would expect, a reboot, and then some webinterface.&lt;/p&gt;

&lt;p&gt;And here the differences start. The whole system boots up much faster.
Not even a third of the time compared to QTS.&lt;/p&gt;

&lt;p&gt;One important thing: As TrueNAS scale is Debian based, and hence a
linux kernel, it automatically detects and assembles the old RAID
arrays that QTS put on. Which TrueNAS can do nothing with, so it helps
to manually stop them and wipe the disks.&lt;/p&gt;

&lt;p&gt;Afterwards I put ZFS on the disks, with a similar setup to what I had
before. The spinning rust are the data disks in a RAIDZ2 setup, the
two SSDs are added as cache devices. Unlike MDADM, ZFS does not have a
long sync process. Also unlike the MDADM/LVM/EXT4 setup from before,
ZFS works different. It manages the raid thing but it also does the
volume and filesystem parts. Quite different handling, and I’m still
getting used to it, so no, I won’t write some ZFS introduction now.&lt;/p&gt;

&lt;h2 id=&quot;features&quot;&gt;Features&lt;/h2&gt;
&lt;p&gt;The two systems can not be compared completly, they are having a
pretty different target audience. QNAP is more for the user that wants
some network storage that offers a ton of extra features easily
available via a clickable interface. While TrueNAS appears more
oriented to people that want a fast but reliable storage system.
TrueNAS does not offer all the extra bloat the QNAP delivers. Still,
you have the ability to run virtual machines and it seems it comes
with Rancher, so some kubernetes/container ability is there. It lacks
essential features like assigning PCI devices to virtual machines, so
is not useful right now, but I assume that will come in a future
version.&lt;/p&gt;

&lt;p&gt;I am still exploring it all, but I like what I have right now. Still
rebuilding my setup to have all shares exported and used again, but
the most important are working already.&lt;/p&gt;
</content>
      
      
      
        <category term="truenas" />
      
        <category term="qnap" />
      
      
        <summary>History, SetupSo for quite some time I have a QNAP TS-873x here, equipped with 8Western Digital Red 10 TB disks, plus 2 WD Blue 500G M2 SSDs. The QNAPitself has an “AMD Embedded R-Series RX-421MD” with 4 cores and wasequipped with 48G RAM.</summary>
      
    </entry>
  
    <entry>
      <title>Rust? Munin? munin-plugin…</title>
      <link href="https://blog.ganneff.de/2022/05/rust-munin-munin-plugin.html" rel="alternate" type="text/html" title="Rust? Munin? munin-plugin..." />
      <published>2022-05-19T22:33:49+02:00</published>
       <updated>2022-05-19T22:33:49+02:00</updated>
      <id>https://blog.ganneff.de/2022/05/rust-munin-munin-plugin</id>
      <content type="html" xml:base="https://blog.ganneff.de/2022/05/rust-munin-munin-plugin.html">&lt;p&gt;My first Rust crate: &lt;a href=&quot;https://crates.io/crates/munin-plugin&quot;&gt;munin-plugin&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sooo, some time ago I had to rewrite a &lt;a href=&quot;https://packages.debian.org/munin &quot;&gt;munin &lt;/a&gt; plugin from
Shell to Rust, due to the shell version going crazy after some runtime
and using up a CPU all for its own. Sure, it only did that on Systems
with Oracle Database installed, so that monster seems to be bad (who
would have guessed?), but somehow I had to fixup this plugin and
wasn’t allowed to drop that wannabe-database.&lt;/p&gt;

&lt;p&gt;A while later I wrote a plugin to graph Fibre Channel Host data, and
then Network interface statistics, all with a one-second resolution
for the graphs, to allow one to zoom in and see &lt;em&gt;every&lt;/em&gt; spike. Not
have RRD round of the interesting parts.&lt;/p&gt;

&lt;p&gt;As one can imagine, that turns out to be a lot of very similar code -
after all, most of the difference is in the graph config statements
and actual data gathering, but the rest of code is just the same.&lt;/p&gt;

&lt;p&gt;As I already know there are more plugins (hello rsyslog statistics) I
have to (sometimes re-)write in Rust, I took some time and wrote me a
Rust library to make writing munin-plugins in Rust easier. Yay, my
first &lt;a href=&quot;https://crates.io/crates/munin-plugin&quot;&gt;crate on crates.io&lt;/a&gt; (and
wrote lots of &lt;a href=&quot;https://docs.rs/munin-plugin/latest/munin_plugin/&quot;&gt;docs&lt;/a&gt; for it).&lt;/p&gt;

&lt;p&gt;By now I made my &lt;a href=&quot;https://github.com/Ganneff/cpu1sec&quot;&gt;1 second resolution CPU load
plugin&lt;/a&gt; and the &lt;a href=&quot;https://github.com/Ganneff/if1sec&quot;&gt;1 second
resolution Network interface
plugin&lt;/a&gt; use this lib already. To
test less complicated plugins with the lib, I took the munin default
plugin “load” (Linux variant) and made a Rust version from it, but
mostly to see that something as simple as that is also easy to
implement: &lt;a href=&quot;https://github.com/Ganneff/munin-load&quot;&gt;Munin load&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I got some idea on how to provide a useful default implementation of
the fetch function, so one can write even less code, when using this
library.&lt;/p&gt;

&lt;p&gt;It is my first library in Rust, so if you see something bad or missing
in there, feel free to open issues or pull requests.&lt;/p&gt;

&lt;p&gt;Now, having done this, one thing missing: Someone to (re)write munin
itself in something that is actually fast… Not munin-node, but
munin. Or maybe the RRD usage, but with a few hundred nodes in it,
with loads of graphs, we had to adjust munin code and change some
timeout or it would commit suicide regularly. And some other code
change for not always checking for a rename, or something like it. And
only run parts of the default cronjob once an hour, not on every
update run. And switch to fetching data over ssh (and munin-async on
the nodes). And rrdcached with loads of caching for the trillions of
files (currently amounts to ~800G of data).. And it still needs way
more CPU than it should. Soo, lots of possible optimizations hidden in
there. Though I bet a non-scripting language rewrite might gain the
most. (Except, of course, someone needs to do it… :) )&lt;/p&gt;
</content>
      
      
      
        <category term="rust" />
      
        <category term="munin" />
      
      
        <summary>My first Rust crate: munin-plugin</summary>
      
    </entry>
  
    <entry>
      <title>Another shell script moved to rust</title>
      <link href="https://blog.ganneff.de/2022/03/another-shell-script-moved-to-rust.html" rel="alternate" type="text/html" title="Another shell script moved to rust" />
      <published>2022-03-20T13:23:33+01:00</published>
       <updated>2022-03-20T13:23:33+01:00</updated>
      <id>https://blog.ganneff.de/2022/03/another-shell-script-moved-to-rust</id>
      <content type="html" xml:base="https://blog.ganneff.de/2022/03/another-shell-script-moved-to-rust.html">&lt;h1 id=&quot;shell-rust&quot;&gt;Shell? Rust!&lt;/h1&gt;
&lt;p&gt;Not the first shell script I took and made a rust version of, but
probably &lt;em&gt;my&lt;/em&gt; largest yet. This time I took my little &lt;a href=&quot;https://github.com/Ganneff/tm&quot;&gt;tm (tmux
helper)&lt;/a&gt; tool which is (well, was) a
bit more than 600 lines of shell, and converted it to
&lt;a href=&quot;https://www.rust-lang.org/&quot;&gt;Rust&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I got most of the functionality done now, only one major part is
missing.&lt;/p&gt;

&lt;h2 id=&quot;whats-tm&quot;&gt;What’s tm?&lt;/h2&gt;
&lt;p&gt;tm started as a tiny shell script to make handling
&lt;a href=&quot;https://github.com/tmux/tmux/wiki&quot;&gt;tmux&lt;/a&gt; easier. The first commit in
git was in July 2013, but I started writing and using it in 2011. It
started out as a kind-of wrapper around ssh, opening tmux windows with
an ssh session on some other hosts. It quickly gained support to open
multiple ssh sessions in one window, telling tmux to synchronize input
(send input to all targets at once), which is great when you have a
set of machines that ought to get the same commands.&lt;/p&gt;

&lt;h3 id=&quot;tm-vs-clusterssh--mussh&quot;&gt;tm vs clusterssh / mussh&lt;/h3&gt;
&lt;p&gt;In spirit it is similar to clusterssh or mussh, allowing to run the
same command on many hosts at the same time. clusterssh sets out to
open new terminals (xterm) per host and gives you an input line, that
it sends everywhere. mussh appears to take your command and then send
it to all the hosts. Both have disadvantages in my opinion: clusterssh
opens lots of xterm windows, and you can not easily switch between
multiple sessions, mussh just seems to send things over ssh and be
done.&lt;/p&gt;

&lt;p&gt;tm instead &lt;em&gt;“just”&lt;/em&gt; creates a tmux session, telling it to ssh to the
targets, possibly setting the tmux option to send input to all panes.
And leaves all the rest of the handling to tmux. So you can&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;detach a session and reattach later easily,&lt;/li&gt;
  &lt;li&gt;use tmux great builtin support for copy/paste,&lt;/li&gt;
  &lt;li&gt;see all output, modify things even for one machine only,&lt;/li&gt;
  &lt;li&gt;“zoom” in to one machine that needs just ONE bit different (cssh can
do this too),&lt;/li&gt;
  &lt;li&gt;let colleagues also connect to your tmux session, when needed,&lt;/li&gt;
  &lt;li&gt;easily add more machines to the mix, if needed,&lt;/li&gt;
  &lt;li&gt;and all the other extra features tmux brings.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;more-tm&quot;&gt;More tm&lt;/h3&gt;
&lt;p&gt;tm also supports just attaching to existing sessions as well as
killing sessions, mostly for lazyness (less to type than using tmux
directly).&lt;/p&gt;

&lt;p&gt;At some point tm gained support for setting up sessions according to
some “session file”. It knows two formats now, one is simple and
mostly a list of hostnames to open synchronized sessions for. This may
contain LIST commands, which let tm execute that command, expected
output is list of hostnames (or more LIST commands) for the session.
That, combined with the replacement part, lets us have one config file
that opens a set of VMs based on tags our
&lt;a href=&quot;https://ganeti.org/&quot;&gt;Ganeti&lt;/a&gt; runs, based on tags. It is simply a LIST
command asking for VMs tagged with the replacement arg and up. Very
handy. Or also “all VMs on host X”.&lt;/p&gt;

&lt;p&gt;The second format is basically “free form tmux commands”. Mostly
“commandline tmux call, just drop the tmux in front” collection.&lt;/p&gt;

&lt;p&gt;Both of them supporting a crude variable replacement.&lt;/p&gt;

&lt;h1 id=&quot;conversion-to-rust&quot;&gt;Conversion to Rust&lt;/h1&gt;
&lt;p&gt;Some while ago I started playing with Rust and it somehow ‘clicked’, I
do like it. My local git tells me, that I tried starting off with
&lt;a href=&quot;https://go.dev/&quot;&gt;go&lt;/a&gt; in 2017, but that appearently did not work out.
Fun, everywhere I can read says that Rust ought to be harder to learn.&lt;/p&gt;

&lt;p&gt;So by now I have most of the functionality implemented in the Rust
version, even if I am sure that the code isn’t a good Rust example.
I’m learning, after all, and already have adjusted big parts of it,
multiple times, whenever I learn (and understand) something more - and
am also sure that this will happen again…&lt;/p&gt;

&lt;h2 id=&quot;compatibility-with-old-tm&quot;&gt;Compatibility with old tm&lt;/h2&gt;
&lt;p&gt;It turns out that my goal of staying compatible with the behaviour of
the old shell script does make some things rather complicated. For
example, the LIST commands in session config files - in shell I just
execute them commands, and shell deals with variable/parameter
expansion, I &lt;em&gt;just&lt;/em&gt; set IFS to newline only and read in what I get
back. Simple. Because shell is doing a lot of things for me.&lt;/p&gt;

&lt;p&gt;Now, in Rust, it is a different thing at all:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Properly splitting the line into shell words, taking care of quoting
(can’t simply take whitespace) (there is &lt;a href=&quot;https://docs.rs/shlex/latest/shlex/&quot;&gt;shlex&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Expanding specials like ~ and $HOME (there is
&lt;a href=&quot;https://docs.rs/home-dir/latest/home_dir/&quot;&gt;home_dir&lt;/a&gt;).&lt;/li&gt;
  &lt;li&gt;Supporting environment variables in general, tm has some that adjust
behaviour of it. Which shell can use globally. Used
&lt;a href=&quot;https://docs.rs/lazy_static/latest/lazy_static/&quot;&gt;lazy_static&lt;/a&gt; for a
similar effect - they aren’t going to change at runtime ever,
anyways.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Properly supporting the commandline arguments also turned out to be a
bit more work. Rust appearently has multiple crates supporting this, I
settled on &lt;a href=&quot;https://docs.rs/clap/latest/clap/&quot;&gt;clap&lt;/a&gt;, but as tm
supports “getopts”-style as well as free-form arguments (subcommands
in clap), it takes a bit to get that interpreted right.&lt;/p&gt;

&lt;h2 id=&quot;speed&quot;&gt;Speed&lt;/h2&gt;
&lt;p&gt;Most of the time entirely unimportant in the tool that tm is (open a
tmux with one to some ssh connections to some places is not exactly
hard or time consuming), there are situations, where one can notice
that it’s calling out to tmux over and over again, for every single
bit to do, and that just takes time: Configurations that open sessions
to 20 and more hosts at the same time especially lag in setup time.
(My largest setup goes to 443 panes in one window). The compiled Rust
version is so much faster there, it’s just great. Nice side effect,
that is. And yes, in the end it is also “only” driving tmux, still, it
takes less than half the time to do so.&lt;/p&gt;

&lt;h2 id=&quot;code-fun-parts&quot;&gt;Code, Fun parts&lt;/h2&gt;
&lt;p&gt;As this is still me learning to write Rust, I am sure the code has
lots to improve. Some of which I will sure find on my own, but if you
have time, I love PRs (or just mails with hints).&lt;/p&gt;

&lt;h3 id=&quot;github&quot;&gt;Github&lt;/h3&gt;
&lt;p&gt;Also the first time I used Github Actions to see how it goes. Letting
it build, test, run
&lt;a href=&quot;https://github.com/rust-lang/rust-clippy&quot;&gt;clippy&lt;/a&gt; and also run a &lt;a href=&quot;https://app.codecov.io/gh/Ganneff/tm&quot;&gt;code
coverage tool&lt;/a&gt; (Yay, more than
50% covered…) on it. Unsure my tests are good, I am not used to
writing tests for code, but hey, coverage!&lt;/p&gt;

&lt;h2 id=&quot;up-next&quot;&gt;Up next&lt;/h2&gt;
&lt;p&gt;I do have to implement the last missing feature, which is reading the
other config file format. A little scared, as that means somehow
translating those lines into correct calls within the
&lt;a href=&quot;https://docs.rs/tmux_interface/latest/tmux_interface/&quot;&gt;tmux_interface&lt;/a&gt;
I am using, not sure that is easy. I &lt;strong&gt;could&lt;/strong&gt; be bad and just shell
out to tmux on it all the time, but somehow I don’t like the thought
of doing that. Maybe (ab)using the control mode, but then, why would I
use tmux_interface, so trying to handle it with that first.&lt;/p&gt;

&lt;p&gt;Afterwards I want to gain a new command, to save existing sessions and
be able to recreate them easily. Shouldn’t be too hard, tmux has a way
to get at that info, somewhere.&lt;/p&gt;
</content>
      
      
      
        <category term="ssh" />
      
        <category term="rust" />
      
      
        <summary>Shell? Rust!Not the first shell script I took and made a rust version of, butprobably my largest yet. This time I took my little tm (tmuxhelper) tool which is (well, was) abit more than 600 lines of shell, and converted it toRust.</summary>
      
    </entry>
  
    <entry>
      <title>Scan for SSH private keys without passphrase</title>
      <link href="https://blog.ganneff.de/2022/03/scan-for-ssh-private-keys-without-passphrase.html" rel="alternate" type="text/html" title="Scan for SSH private keys without passphrase" />
      <published>2022-03-03T21:32:06+01:00</published>
       <updated>2022-03-03T21:32:06+01:00</updated>
      <id>https://blog.ganneff.de/2022/03/scan-for-ssh-private-keys-without-passphrase</id>
      <content type="html" xml:base="https://blog.ganneff.de/2022/03/scan-for-ssh-private-keys-without-passphrase.html">&lt;h1 id=&quot;ssh-private-key-scanner-keys-without-passphrase&quot;&gt;SSH private key scanner (keys without passphrase)&lt;/h1&gt;

&lt;p&gt;So for policy reasons, customer wanted to ensure that every SSH
private key in use by a human on their systems has a passphrase set.
And asked us to make sure this is the case.&lt;/p&gt;

&lt;p&gt;There is no way in SSH to check this during connection, so client side
needs to be looked at. Which means looking at actual files on the
system.&lt;/p&gt;

&lt;p&gt;Turns out there are multiple formats for the private keys - and I
really do not want to implement something able to deal with that on my
own.&lt;/p&gt;

&lt;p&gt;OpenSSH to the rescue, it ships a little tool &lt;em&gt;ssh-keygen&lt;/em&gt;, most
commonly known for its ability to generate SSH keys. But it can do
much more with keys. One action is interesting here for our case: The
ability to print out the public key to a given private key. For a key
that is unprotected, this will just work. A key with a passphrase
instead leads to it asking you for one.&lt;/p&gt;

&lt;p&gt;So we have our way to check if a key is protected by a passphrase. Now
we only need to find all possible keys (note, the requirement is not
&lt;em&gt;“keys in .ssh/”&lt;/em&gt;, but &lt;em&gt;all possible&lt;/em&gt;, so we need to scan for them.&lt;/p&gt;

&lt;p&gt;But we do not want to run &lt;em&gt;ssh-keygen&lt;/em&gt; on just any file, we would like
to do it when we are halfway sure, that it is actually a key. Well,
turns out, even though SSH has multiple formats, they all appear to
have the string &lt;strong&gt;PRIVATE KEY&lt;/strong&gt; somewhere very early (usually first
line). And they are tiny - even a 16384bit RSA key is just above 12000
bytes long.&lt;/p&gt;

&lt;p&gt;Lets find every file thats less then 13000 bytes and has the magic
string in it, and throw it at &lt;em&gt;ssh-keygen&lt;/em&gt; - if we get a public key
back, flag it. Also, we supply a random (ohwell, hardcoded)
passphrase, to avoid it prompting for any.&lt;/p&gt;

&lt;p&gt;Scanning the whole system, one will find quite a surprising number of
“unprotected” SSH keys. Well, better description possibly “Unprotected
RSA private keys”, so the output does need to be checked by a human.&lt;/p&gt;

&lt;p&gt;This, of course, can be done in shell, quite simple. So i wrote some
Rust code instead, as I am still on my task to try and learn more of
it. If you are interested, you can &lt;a href=&quot;https://github.com/Ganneff/sshprivscanner&quot;&gt;find sshprivscanner and play with
it&lt;/a&gt;, patches/fixes/whatever
welcome.&lt;/p&gt;
</content>
      
      
      
        <category term="ssh" />
      
        <category term="rust" />
      
      
        <summary>SSH private key scanner (keys without passphrase)</summary>
      
    </entry>
  
    <entry>
      <title>Funny CPU usage - rewrite it in rust</title>
      <link href="https://blog.ganneff.de/2022/02/funny-cpu-usage-rewrite-in-rust.html" rel="alternate" type="text/html" title="Funny CPU usage - rewrite it in rust" />
      <published>2022-02-16T21:23:48+01:00</published>
       <updated>2022-02-16T21:23:48+01:00</updated>
      <id>https://blog.ganneff.de/2022/02/funny-cpu-usage-rewrite-in-rust</id>
      <content type="html" xml:base="https://blog.ganneff.de/2022/02/funny-cpu-usage-rewrite-in-rust.html">&lt;h1 id=&quot;munin-plugin-and-its-cpu-usage-and-a-rewrite-in-rust&quot;&gt;Munin plugin and it’s CPU usage (and a rewrite in rust)&lt;/h1&gt;

&lt;p&gt;With my last blog on the &lt;a href=&quot;/2022/01/funny-cpu-usage.html&quot;&gt;Munin plugins CPU usage&lt;/a&gt; I complained about Oracle
Linux doing something really weird, driving up CPU usage when running
a fairly simple Shell script with a loop in.&lt;/p&gt;

&lt;p&gt;Turns out, I was wrong. It is &lt;strong&gt;not&lt;/strong&gt; OL7 that makes this problem show
up. It appears to be something from the Oracle &lt;em&gt;“Enterprise”&lt;/em&gt; Database
installed on the system, that makes it go this crazy. I’ve now had
this show up on RedHat7 systems too, and the only thing that singles
them out is that overpriced index card system on it.&lt;/p&gt;

&lt;p&gt;I still don’t know what the actual reason for this is, and honestly,
don’t have enough time to dig deep into it. It is not something that a
bit of debugging/tracing finds - especially as it does start out all
nice, and accumulates more CPU usage over time. Which would suggest
some kind of leak leading to more processing needed, or so - but then
it is only CPU affected, not memory, and ONLY on systems with that
database on. Meh.&lt;/p&gt;

&lt;p&gt;Well, I recently (December vacation) got me to look deeper into
learning Rust. My first project with that was a multi-threaded milter
to do some TLS checks on outgoing mails (kind of fun customer
requirements there), and heck, Rust did make that a surprisingly easy
task in the end. (Comparing the old, single-threaded C code with my
multi-threaded Rust version, a third of the code length doing more,
and being way easier to extend with wanted new features is nice).&lt;/p&gt;

&lt;p&gt;So my second project was “Replace this shell script with a Rust binary
doing the same”. Hell yeah. Didn’t take that long and looks good
(well, the result. Not sure about the code. People knowing rust may
possibly scratch out eyes when looking at it). Not
yet running for that long, but even compared to the shell on systems
that did not show the above mentioned bugs (read: Debian, without
Oracle foo), uses WAY less CPU (again, mentioned by highly accurate
outputs of the top command). So longer term I hope this version won’t
run into the same problems as the shell one. Time will tell.&lt;/p&gt;

&lt;p&gt;If you are interested in the code, go &lt;a href=&quot;https://github.com/Ganneff/if1sec&quot;&gt;find it
here&lt;/a&gt;, and if you happen to know
rust and not run away screaming, I’m happy for tips and code fixes,
I’m sure this can be improved lots. (At least cargo clippy is happy,
so basics are done…)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: According to munin, the rust version creates 14
forks/second less than the shell one. And the fork rate change is same
on machines with/without the database. That 14 is more than I would
have guessed. CPU usage as expected: only on the problem hosts with
Oracle Database installed you can see a huge difference, otherwise it
is not an easily noticable difference. That is, on an otherwise idle
host (munin graph shows average use of low one-digit numbers), one can
see a drop of around 1% in the CPU usage graph from munin. Ohwell,
poor Shell.&lt;/p&gt;
</content>
      
      
      
        <category term="bash" />
      
        <category term="munin" />
      
      
        <summary>Munin plugin and it’s CPU usage (and a rewrite in rust)</summary>
      
    </entry>
  
    <entry>
      <title>Funny CPU usage</title>
      <link href="https://blog.ganneff.de/2022/01/funny-cpu-usage.html" rel="alternate" type="text/html" title="Funny CPU usage" />
      <published>2022-01-19T21:56:17+01:00</published>
       <updated>2022-01-19T21:56:17+01:00</updated>
      <id>https://blog.ganneff.de/2022/01/funny-cpu-usage</id>
      <content type="html" xml:base="https://blog.ganneff.de/2022/01/funny-cpu-usage.html">&lt;h1 id=&quot;munin-plugin-and-its-cpu-usage-shell-fixup&quot;&gt;Munin plugin and it’s CPU usage (shell fixup)&lt;/h1&gt;

&lt;p&gt;So at work we do have a &lt;a href=&quot;https://packages.debian.org/munin &quot;&gt;munin &lt;/a&gt; server running, and one of
the graphs we do for every system is a network statistics one with a
resolution of 1 second. That’s a simple enough script to have, and it
is working nicely - on 98% of our machines. You just don’t notice the
data gatherer at all, so that we also have some other graphs done with
a 1 second resolution. For some, this really helps.&lt;/p&gt;

&lt;h2 id=&quot;basics&quot;&gt;Basics&lt;/h2&gt;
&lt;p&gt;The basic code for this is simple. There is a bunch of stuff to start
the background gathering, some to print out the config, and some to
hand out the data when munin wants it. Plenty standard.&lt;/p&gt;

&lt;p&gt;The interesting bit that goes wrong and uses too much CPU on &lt;strong&gt;one&lt;/strong&gt;
Linux Distribution is this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;run_acquire&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;echo&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;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pidfile&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; :&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
     &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;TSTAMP&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;date&lt;/span&gt; +%s&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IFACE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;_tx.value &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;TSTAMP&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;:&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /sys/class/net/&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IFACE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/statistics/tx_bytes &lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cache&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;
     &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IFACE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;_rx.value &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;TSTAMP&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;:&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /sys/class/net/&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IFACE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/statistics/rx_bytes &lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cache&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;
     &lt;span class=&quot;c&quot;&gt;# Sleep for the rest of the second&lt;/span&gt;
     &lt;span class=&quot;nb&quot;&gt;sleep &lt;/span&gt;0.&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;%04d&apos;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;$((&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;10000&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;#$(date +%4N))))&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;That code works, and none of Debian wheezy, stretch and buster as well
as RedHat 6 or 7 shows anything, it just works, no noticable load generated.&lt;/p&gt;

&lt;p&gt;Now, Oracle Linux 7 thinks differently. The above code run there
generates between 8 and 15% CPU usage (on fairly recent Intel CPUs,
but that shouldn’t matter). (CPU usage measured with the highly
accurate use of top and looking what it tells…)&lt;/p&gt;

&lt;p&gt;Whyever.&lt;/p&gt;

&lt;h2 id=&quot;fixing&quot;&gt;Fixing&lt;/h2&gt;
&lt;p&gt;Ok, well, the code above isn’t all the nicest shell, actually. There
is room for improvement. But beware, the older the bash, the less one
can fix it.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;So, first of, there are two useless uses of cat. Bash can do that
for us, just use the &lt;em&gt;$(&amp;lt; /PATH/TO/FILE )&lt;/em&gt; way.&lt;/li&gt;
  &lt;li&gt;Oh, Bash5 knows the epoch directly, we can replace the date call for
the timestamp and use &lt;em&gt;${EPOCHSECONDS}&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Too bad Bash4 can’t do that. But hey, it’s builtin printf can help
out, a nice &lt;em&gt;TSTAMP=$(printf ‘%(%s)T\n’ -1)&lt;/em&gt; works.&lt;/li&gt;
  &lt;li&gt;Unfortunately, Bash4.2 and later, not 4.1, and meh, we have a 4.1
system, so that has to stay with the date call there.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Taking that, we end up with 3 different possible versions, depending
on the Bash on the system.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;obtain5&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;## Purest bash version, Bash can tell us epochs directly&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IFACE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;_tx.value &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;EPOCHSECONDS&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;:&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&amp;lt;/sys/class/net/&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IFACE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/statistics/tx_bytes&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cache&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IFACE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;_rx.value &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;EPOCHSECONDS&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;:&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&amp;lt;/sys/class/net/&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IFACE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/statistics/rx_bytes&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cache&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;# Sleep for the rest of the second&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;sleep &lt;/span&gt;0.&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;%04d&apos;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;$((&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;10000&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;#$(date +%4N))))&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

obtain42&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;## Bash cant tell us epochs directly, but the builtin printf can&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;TSTAMP&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;%(%s)T\n&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-1&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IFACE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;_tx.value &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;TSTAMP&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;:&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&amp;lt;/sys/class/net/&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IFACE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/statistics/tx_bytes&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cache&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IFACE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;_rx.value &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;TSTAMP&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;:&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&amp;lt;/sys/class/net/&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IFACE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/statistics/rx_bytes&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cache&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;# Sleep for the rest of the second&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;sleep &lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;.&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;%04d&apos;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;$((&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;10000&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;#$(date +%4N))))&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

obtain41&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;## Bash needs help from a tool to get epoch, means one exec() all the time&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;TSTAMP&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;date&lt;/span&gt; +%s&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IFACE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;_tx.value &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;TSTAMP&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;:&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&amp;lt;/sys/class/net/&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IFACE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/statistics/tx_bytes&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cache&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IFACE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;_rx.value &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;TSTAMP&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;:&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&amp;lt;/sys/class/net/&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IFACE&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/statistics/rx_bytes&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cache&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;# Sleep for the rest of the second&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;sleep &lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;.&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;%04d&apos;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;$((&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;10000&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;#$(date +%4N))))&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

run_acquire&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;echo&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;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pidfile&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BASH_VERSINFO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[0]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in
     &lt;/span&gt;5&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; :&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
          &lt;/span&gt;obtain5
        &lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
     4&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BASHVERSION&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[1]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-ge&lt;/span&gt; 2 &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
          while&lt;/span&gt; :&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
            &lt;/span&gt;obtain42
          &lt;span class=&quot;k&quot;&gt;done
        else
          while&lt;/span&gt; :&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
            &lt;/span&gt;obtain41
          &lt;span class=&quot;k&quot;&gt;done
        fi&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;;;&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;esac&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;does-it-help&quot;&gt;Does it help?&lt;/h1&gt;

&lt;p&gt;Oh yes, it does. Oracle Linux 7 appears to use Bash 4.2, so uses
obtain42 and hey, removing one date and two cat calls, and it has a
sane CPU usage of 0 (again, highly accurate number generated from
top…). Appears OL7 is doing heck-what-do-i-know extra, when calling
other tools, for whatever gains, removing that does help (who would
have thought).&lt;/p&gt;

&lt;p&gt;(None of RedHat or Oracle Linux has SELinux turned on, so that one
 shouldn’t bite. But it is clear OL7 doing something extra for
 everything that bash spawns.)&lt;/p&gt;
</content>
      
      
      
        <category term="bash" />
      
        <category term="munin" />
      
      
        <summary>Munin plugin and it’s CPU usage (shell fixup)</summary>
      
    </entry>
  
    <entry>
      <title>Debian NEW Queue, Rust packaging</title>
      <link href="https://blog.ganneff.de/2020/11/debian-new-queue-rust-packaging.html" rel="alternate" type="text/html" title="Debian NEW Queue, Rust packaging" />
      <published>2020-11-03T00:38:00+01:00</published>
       <updated>2020-11-03T00:38:00+01:00</updated>
      <id>https://blog.ganneff.de/2020/11/debian-new-queue,-rust-packaging</id>
      <content type="html" xml:base="https://blog.ganneff.de/2020/11/debian-new-queue-rust-packaging.html">&lt;h1 id=&quot;debian-new-queue&quot;&gt;Debian NEW Queue&lt;/h1&gt;

&lt;p&gt;So for some reason I got myself motivated again to deal with some
packages in Debians &lt;a href=&quot;https://ftp-master.debian.org/new.html&quot;&gt;NEW Queue&lt;/a&gt;.
We had 420 source packages waiting for some kind of processing when I
started, now we are down to something &lt;a href=&quot;https://ftp-master.debian.org/stat.html&quot;&gt;around
10&lt;/a&gt;. (Silly, people keep
uploading stuff…)&lt;/p&gt;

&lt;p&gt;That’s not entirely my own work, others from the team have been active
too, but for those few days I went through a lot of stuff waiting. And
must say it still feels mostly like it did when I somehow stopped
doing much in NEW.&lt;/p&gt;

&lt;p&gt;Except - well, I &lt;strong&gt;feel&lt;/strong&gt; that maintainers are much better in preparing
their packages, especially that dreaded task of getting the copyright
file written seems to be one that is handled much better. Now, thats
not supported by any real numbers, just a feeling, but a good one, I
think.&lt;/p&gt;

&lt;h1 id=&quot;rust&quot;&gt;Rust&lt;/h1&gt;

&lt;p&gt;Dealing with NEW meant I got in contact with one part that currently
generates some friction between the FTP Team and one group of package
maintainers - the Rust team.&lt;/p&gt;

&lt;p&gt;Note: this is, of course, entirely written from my point of view.
Though with the intention of presenting it as objective as possible.
Also, I know what rust is, and have tried a “Hello world” in it, but
that’s about my &lt;em&gt;deep&lt;/em&gt; knowledge of it…&lt;/p&gt;

&lt;h2 id=&quot;the-problem&quot;&gt;The problem&lt;/h2&gt;

&lt;p&gt;Libraries in rust are bundled/shipped/whatever in something called
crates, and you manage what your stuff needs and provides with a tool
called &lt;em&gt;cargo&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;A library (one per crate) can provide multiple features, say a TLS lib
can link against gnutls or openssl or some other random
implementation. Such features may even be combinable in various
different ways, so one can have a high number of possible feature
combinations for one crate.&lt;/p&gt;

&lt;p&gt;There is a tool called &lt;a href=&quot;https://packages.debian.org/debcargo &quot;&gt;debcargo &lt;/a&gt; which helps creating a
Debian package out of a crate. And that tool generates so-called
&lt;strong&gt;&lt;em&gt;feature-packages&lt;/em&gt;&lt;/strong&gt;, one per feature / combination thereof.&lt;/p&gt;

&lt;p&gt;Those feature packages are empty packages, only containing a symlink
for their &lt;em&gt;/usr/share/doc/…&lt;/em&gt; directory, so their size is smaller
than the metadata they will produce. Inside the archive and the files
generated by it, stuff that every user everywhere has to download
and their apt has to process. Additionally, any change of those feature
sets means one round through NEW, which is also not ideal.&lt;/p&gt;

&lt;p&gt;So, naturally, the FTP Team dislikes those empty feature packages.
Really, a lot.&lt;/p&gt;

&lt;p&gt;There appears to be a different way. Not having the feature packages,
but putting all the combinations into a &lt;em&gt;Provides&lt;/em&gt; header. That
sometimes works, but has two problems:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It can generate really long Provides: lines. I mean, REALLY
&lt;strong&gt;REALLY&lt;/strong&gt; &lt;strong&gt;&lt;em&gt;REALLY&lt;/em&gt;&lt;/strong&gt; long. Somewhat around 250kb is the current
record. Thats long enough that a tool (not dak itself) broke on it.
Sure, that tool needs to be fixed, but still, that’s not nice.
Currently preferred from us, though.&lt;/li&gt;
  &lt;li&gt;Some of the features may need different dependencies (say, gnutls
vs openssl), should those conflict with each other, you can not
combine them into one package.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;solutions&quot;&gt;Solutions&lt;/h2&gt;

&lt;p&gt;Currently we do not have a good one. The rust maintainers and the ftp
team are talking, exploring various ideas, we will see what will come
out.&lt;/p&gt;

&lt;h1 id=&quot;devel-archive--component&quot;&gt;Devel archive / Component&lt;/h1&gt;

&lt;p&gt;One of the possible solutions for the feature package problem would be
something that another set of packages could also make good use of, I
think. The introduction of a new archive or component, meant only for
packages that are needed to build something, but where users are
discouraged from ever using them.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;Well, take golang as an example. While we have a load of
golang-something packages in Debian, and they are used for building
applications written in go - none of those golang-something are meant
to be installed by users. If you use the language and develop in it,
the &lt;strong&gt;go get&lt;/strong&gt; way is the one you are expected to use.&lt;/p&gt;

&lt;p&gt;So having an archive (or maybe component like main or contrib) that,
by default, won’t be activated for users, but only for things like
buildds or archive rebuilds, will make one problem (hated metadata
bloat) be evaluated wildly different.&lt;/p&gt;

&lt;p&gt;It may also allow a more relaxed processing of binary-NEW (easier
additions of new feature packages).&lt;/p&gt;

&lt;h2 id=&quot;but-but-but&quot;&gt;But but but&lt;/h2&gt;

&lt;p&gt;Yes, it is not the most perfect solution. Without taking much energy
to think about, it requires&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;an adjustment in how main is handled. Right now we have the golden
rule that &lt;em&gt;main is self contained&lt;/em&gt;, that is, things in it may not
need anything outside it for building or running. That would need
to be adjusted for building. (Go as well as &lt;em&gt;currently&lt;/em&gt; rust are
always building static binaries, so no library dependencies there).&lt;/li&gt;
  &lt;li&gt;It would need handling for the release, that is, the release team
would need to deal with that archive/component too. We haven’t,
yet, talked to them (still, slowly, discussing inside FTP Team).
So, no idea how many rusty knives they want to sink into our nice
bodies for that idea…&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;final&quot;&gt;Final&lt;/h1&gt;

&lt;p&gt;Well, it is still very much open. Had an IRC meeting with the rust
people, will have another end of November, it will slowly go forward.
And maybe someone comes up with an entire new idea that we all love.
Don’t know, time will tell.&lt;/p&gt;
</content>
      
      
      
        <category term="NEW" />
      
        <category term="rust" />
      
      
        <summary>Debian NEW Queue</summary>
      
    </entry>
  
</feed>
