<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>El web de l&#x27;Eudald</title>
    <subtitle>Aquest és el meu web.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://eudald.gr/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://eudald.gr"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-03-25T00:00:00+00:00</updated>
    <id>https://eudald.gr/atom.xml</id>
    <entry xml:lang="en">
        <title>Entrypoint per contenidors distroless amb .NET single-file</title>
        <published>2026-03-25T00:00:00+00:00</published>
        <updated>2026-03-25T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://eudald.gr/posts/20260325p1/"/>
        <id>https://eudald.gr/posts/20260325p1/</id>
        
        <content type="html" xml:base="https://eudald.gr/posts/20260325p1/">&lt;p&gt;.NET 10 porta una novetat que em sembla més important del que pot semblar a primera vista: &lt;code&gt;dotnet run app.cs&lt;&#x2F;code&gt; i &lt;code&gt;dotnet publish app.cs&lt;&#x2F;code&gt;.
En resum: pots agafar un sol fitxer C#, sense &lt;code&gt;.csproj&lt;&#x2F;code&gt;, i executar-lo o publicar-lo directament.&lt;&#x2F;p&gt;
&lt;p&gt;Quan ho vaig veure, la lectura fàcil era &quot;ah, finalment .NET té un mode script decent&quot;.
I sí, una mica va per aquí.
Microsoft ho va presentar a l&#x27;article &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;devblogs.microsoft.com&#x2F;dotnet&#x2F;announcing-dotnet-run-app&#x2F;&quot;&gt;Announcing dotnet run app.cs&lt;&#x2F;a&gt; i també hi ha algun resum ràpid com aquest de &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;dev.to&#x2F;mashrulhaque&#x2F;dotnet-run-in-net-10-single-file-c-is-finally-here-1gdi&quot;&gt;dev.to&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Però aquest post no va d&#x27;explicar la feature en abstracte.
Va d&#x27;un use-case molt concret que em sembla especialment bo: fer servir un &lt;code&gt;.cs&lt;&#x2F;code&gt; solt com a entrypoint compilat amb Native AOT per a contenidors hardened, distroless, rootless i sense shell.
L&#x27;exemple real surt de &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;vegops&#x2F;containers&quot;&gt;vegops&#x2F;containers&lt;&#x2F;a&gt;, concretament de la imatge de qBittorrent.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;el-problema-contenidors-sense-shell&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#el-problema-contenidors-sense-shell&quot; aria-label=&quot;Anchor link for: el-problema-contenidors-sense-shell&quot;&gt;El problema: contenidors sense shell&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Quan dius &quot;distroless&quot; aquí no parles només de fer una imatge petita.
Parles d&#x27;una imatge amb el mínim imprescindible a runtime.
En aquest cas concret, l&#x27;entorn va sobre Wolfi&#x2F;Chainguard, sense &lt;code&gt;busybox&lt;&#x2F;code&gt;, sense &lt;code&gt;sh&lt;&#x2F;code&gt;, sense &lt;code&gt;apt&lt;&#x2F;code&gt;, i sense tota la ferralla habitual que acostuma a venir amb una distribució generalista.&lt;&#x2F;p&gt;
&lt;p&gt;A més a més, el contenidor arrenca com a &lt;code&gt;nonroot&lt;&#x2F;code&gt; amb UID &lt;code&gt;65532&lt;&#x2F;code&gt;.
Això és exactament el que vols en una imatge hardened: menys superfície, menys privilegis, menys sorpreses.
El problema és que abans d&#x27;arrencar el procés principal sovint encara necessites una mica de lògica d&#x27;init.&lt;&#x2F;p&gt;
&lt;p&gt;Pot ser copiar una configuració per defecte, o injectar un secret via variable d&#x27;entorn, o bé, substituir el procés correctament perquè el teu servei quedi com a PID 1 i rebi senyals directament.
Amb shell això és trivial.
Sense shell, has de buscar un altre mètode.
Les opcions típiques són un binari petit en &lt;code&gt;Go&lt;&#x2F;code&gt;, &lt;code&gt;Rust&lt;&#x2F;code&gt;, &lt;code&gt;tini&lt;&#x2F;code&gt;, o ara també un fitxer C# compilat amb Native AOT.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;En un contenidor sense shell, el problema no és &quot;com executo una comanda&quot;.
El problema real és &quot;on poso la lògica d&#x27;entrada sense reintroduir dependències i complexitat&quot;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;la-solucio-un-entrypoint-cs-amb-native-aot&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#la-solucio-un-entrypoint-cs-amb-native-aot&quot; aria-label=&quot;Anchor link for: la-solucio-un-entrypoint-cs-amb-native-aot&quot;&gt;La solució: un &lt;code&gt;entrypoint.cs&lt;&#x2F;code&gt; amb Native AOT&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;L&#x27;exemple de qBittorrent ho resolc amb un únic fitxer: &lt;code&gt;entrypoint.cs&lt;&#x2F;code&gt;.
No hi ha projecte, ni dependències externes, ni tan sols runtime .NET dins la imatge final.
Durant el build es compila amb Native AOT i el resultat és un binari autocontingut que acaba a &lt;code&gt;&#x2F;usr&#x2F;bin&#x2F;entrypoint&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;La part interessant és que el mateix fitxer porta directives &lt;code&gt;#:property&lt;&#x2F;code&gt; per controlar la compilació.
Aquí és on defineixes que vols &lt;code&gt;PublishAot=true&lt;&#x2F;code&gt;, que vols treure símbols, optimitzar per mida, retallar metadades i desactivar coses que no calen com el suport de stack traces.&lt;&#x2F;p&gt;
&lt;p&gt;El programa fa tres coses i prou: garantir que hi ha configuració, rotar la password per defecte si encara hi és, i fer un &lt;code&gt;execv()&lt;&#x2F;code&gt; sobre el binari real de qBittorrent.
Res més.
Just el tipus d&#x27;entrypoint petit, específic i visible que vols en un contenidor distroless.&lt;&#x2F;p&gt;
&lt;p&gt;Aquest és l&#x27;entrypoint sencer:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;property&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; PublishAot&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;property&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; InvariantGlobalization&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;property&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; StripSymbols&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;property&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; OptimizationPreference&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Size&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;property&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; IlcOptimizationPreference&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Size&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;property&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; StackTraceSupport&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;property&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; UseSystemResourceKeys&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;property&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; IlcTrimMetadata&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;property&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; AssemblyName&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;entrypoint&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;using&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; System&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Runtime&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;InteropServices&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;using&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; System&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Security&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Cryptography&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;using&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; System&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Text&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; string&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; AppBin&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;qbittorrent&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; string&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; ConfigPath&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;qbittorrent&#x2F;etc&#x2F;qBittorrent.conf&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; string&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; DefaultConfigPath&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;usr&#x2F;share&#x2F;qbittorrent&#x2F;qBittorrent.conf&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; string&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; DefaultPasswordHash&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;@ByteArray(188J&#x2F;h&#x2F;wfAYQ9H+mTl&#x2F;7lA==:j&#x2F;+e2SwJUi9g+IPiEG2+Pix9W0IOv2c20QjrmBUhr4TBUXO3fcMv6leeU6qK8834xiq8fngh8ShwYDfYO0w6lg==)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; string&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Alphabet&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;try&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    EnsureConfig&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    RotateDefaultPassword&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    Exec&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;catch&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Exception&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; ex&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    Console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;WriteLine&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;ex&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;Message&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    Environment&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Exit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;static&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; void&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; EnsureConfig&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    Directory&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;CreateDirectory&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;Path&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;GetDirectoryName&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;ConfigPath&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;!&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    var&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; inlineConfig&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; Environment&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;GetEnvironmentVariable&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;QBITTORRENT_CONFIG&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;IsNullOrEmpty&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;inlineConfig&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        File&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;WriteAllText&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;ConfigPath&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; inlineConfig&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;File&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Exists&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;ConfigPath&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        File&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Copy&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;DefaultConfigPath&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; ConfigPath&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;static&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; void&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; RotateDefaultPassword&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    var&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; content&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; File&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ReadAllText&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;ConfigPath&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;content&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Contains&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;DefaultPasswordHash&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; StringComparison&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;Ordinal&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    var&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; password&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; RandomString&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    var&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; salt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; RandomString&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    var&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; hash&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; Rfc2898DeriveBytes&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Pbkdf2&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        password&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        Encoding&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;UTF8&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;GetBytes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;salt&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;        100000&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        HashAlgorithmName&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;SHA512&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;        64&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    var&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; replacement&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; $&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;@ByteArray(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;Convert&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ToBase64String&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;Encoding&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;UTF8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;GetBytes&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;salt&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;Convert&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ToBase64String&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;hash&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    var&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; updated&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; content&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Replace&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;DefaultPasswordHash&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; replacement&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; StringComparison&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;Ordinal&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    File&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;WriteAllText&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;ConfigPath&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; updated&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    Console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;WriteLine&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;$&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;qBittorrent admin password: &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;password&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;static&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; string&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; RandomString&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;int&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; length&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    var&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; RandomNumberGenerator&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;GetBytes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    var&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; chars&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; new&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; char&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;length&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;var&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;Length&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        chars&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; Alphabet&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;bytes&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; %&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; Alphabet&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;Length&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; new&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; string&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;chars&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;static&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; void&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Exec&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    var&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; args&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; Environment&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;GetCommandLineArgs&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    var&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; argv&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; new&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; string&lt;&#x2F;span&gt;&lt;span&gt;?&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;args&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;Length&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    argv&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;qbittorrent&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    Array&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Copy&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;args&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; argv&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; args&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;Length&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    argv&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; null&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    var&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; result&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; NativeMethods&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;execv&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;AppBin&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; argv&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    throw&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; new&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Exception&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;$&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;execv(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;AppBin&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;) failed: errno &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;Marshal&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;GetLastPInvokeError&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;, result &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;result&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;static&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; NativeMethods&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    [&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;DllImport&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;libc&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; SetLastError&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    internal&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; static&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; extern&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; int&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; execv&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; filename&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; string&lt;&#x2F;span&gt;&lt;span&gt;?&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; argv&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;desglossament-del-codi&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#desglossament-del-codi&quot; aria-label=&quot;Anchor link for: desglossament-del-codi&quot;&gt;Desglossament del codi&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;configuracio-ensureconfig&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#configuracio-ensureconfig&quot; aria-label=&quot;Anchor link for: configuracio-ensureconfig&quot;&gt;Configuració: &lt;code&gt;EnsureConfig()&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;La primera responsabilitat és assegurar que qBittorrent té un fitxer de configuració usable.
Si existeix la variable d&#x27;entorn &lt;code&gt;QBITTORRENT_CONFIG&lt;&#x2F;code&gt;, el contingut s&#x27;escriu directament a &lt;code&gt;&#x2F;qbittorrent&#x2F;etc&#x2F;qBittorrent.conf&lt;&#x2F;code&gt;.
Si no, i encara no hi ha config, es copia el fitxer per defecte des de &lt;code&gt;&#x2F;usr&#x2F;share&#x2F;qbittorrent&#x2F;qBittorrent.conf&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;És una lògica simple, però és exactament la mena de coses que abans acabaven en un &lt;code&gt;entrypoint.sh&lt;&#x2F;code&gt;.
La diferència és que aquí no depens de tenir shell ni eines externes a runtime.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Un bon detall és que la configuració inline via variable d&#x27;entorn evita haver de muntar scripts auxiliars només per injectar quatre línies de config.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;rotacio-de-password-rotatedefaultpassword&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#rotacio-de-password-rotatedefaultpassword&quot; aria-label=&quot;Anchor link for: rotacio-de-password-rotatedefaultpassword&quot;&gt;Rotació de password: &lt;code&gt;RotateDefaultPassword()&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;La segona responsabilitat és evitar que qBittorrent arrenqui amb el hash per defecte.
El codi llegeix el fitxer, busca el &lt;code&gt;DefaultPasswordHash&lt;&#x2F;code&gt; conegut, i si encara hi es genera una password aleatòria i un salt nou.&lt;&#x2F;p&gt;
&lt;p&gt;Després deriva el hash amb &lt;code&gt;Rfc2898DeriveBytes.Pbkdf2&lt;&#x2F;code&gt;, fent servir &lt;code&gt;SHA512&lt;&#x2F;code&gt;, &lt;code&gt;100000&lt;&#x2F;code&gt; iteracions i una sortida de &lt;code&gt;64&lt;&#x2F;code&gt; bytes.
Amb això construeix el format &lt;code&gt;@ByteArray(...)&lt;&#x2F;code&gt; que qBittorrent espera, substitueix el hash per defecte i escriu el fitxer actualitzat.&lt;&#x2F;p&gt;
&lt;p&gt;Finalment imprimeix la nova password a stdout.
En un contenidor això és pràctic perquè la pots recuperar directament dels logs de la primera arrencada, sense inventar un mecanisme paral·lel.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;process-replacement-exec&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#process-replacement-exec&quot; aria-label=&quot;Anchor link for: process-replacement-exec&quot;&gt;Process replacement: &lt;code&gt;Exec()&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;La tercera peça és la més pròpia de contenidors &quot;de debò&quot;: fer un &lt;code&gt;execv()&lt;&#x2F;code&gt; via P&#x2F;Invoke a &lt;code&gt;libc&lt;&#x2F;code&gt;.
Això substitueix el procés actual pel binari real de qBittorrent, en lloc de llançar un subprocess i quedar-te amb un wrapper pel mig.&lt;&#x2F;p&gt;
&lt;p&gt;Aquest detall importa perquè l&#x27;entrypoint acaba desapareixent i qBittorrent queda com a PID 1.
Això vol dir senyals directes, menys problemes de reaping, i un comportament molt més net quan el runtime del contenidor envia &lt;code&gt;SIGTERM&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Si has fet servir scripts shell com a entrypoint, ja saps el patró: o fas &lt;code&gt;exec&lt;&#x2F;code&gt;, o tard o d&#x27;hora acabes amb shutdowns estranys.
Aquí es resol igual, però sense shell.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;com-es-compila-i-s-integra&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#com-es-compila-i-s-integra&quot; aria-label=&quot;Anchor link for: com-es-compila-i-s-integra&quot;&gt;Com es compila i s&#x27;integra&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Al pipeline de build, el fitxer es compila directament des de &lt;code&gt;melange.yaml&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; B&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;uild entrypoint (Native AOT)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;uns&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    arch=&amp;quot;$(uname -m | sed &amp;#39;s&#x2F;aarch64&#x2F;arm64&#x2F;;s&#x2F;x86_64&#x2F;x64&#x2F;&amp;#39;)&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    dotnet publish entrypoint.cs -c Release -r &amp;quot;linux-${arch}&amp;quot; -o .&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; I&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;nstall artifacts&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;uns&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    install -Dm755 entrypoint &amp;quot;${{targets.destdir}}&#x2F;usr&#x2F;bin&#x2F;entrypoint&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Després, a &lt;code&gt;apko.yaml&lt;&#x2F;code&gt;, la imatge final defineix aquest binari com a entrypoint i arrenca com a usuari &lt;code&gt;nonroot&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ccounts&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  g&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;roups&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; g&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;roupname&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;onroot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      g&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 65532&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;sers&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;sername&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;onroot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      u&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 65532&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;      g&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 65532&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;un-as&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;65532&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ntrypoint&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;  c&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ommand&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;usr&#x2F;bin&#x2F;entrypoint&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;El resultat és bastant elegant: el binari viu a &lt;code&gt;&#x2F;usr&#x2F;bin&#x2F;entrypoint&lt;&#x2F;code&gt;, la imatge no necessita ni runtime de .NET ni shell, i tota la lògica d&#x27;inicialització queda encapsulada en una peça petita i auditable.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;per-que-c-i-no-go-rust-shell&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#per-que-c-i-no-go-rust-shell&quot; aria-label=&quot;Anchor link for: per-que-c-i-no-go-rust-shell&quot;&gt;Per què C# i no Go&#x2F;Rust&#x2F;shell?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Si ja tens .NET disponible al pipeline de build, afegir un fitxer &lt;code&gt;.cs&lt;&#x2F;code&gt; és gairebé trivial.
No has de crear cap projecte, no has de mantenir dependències de tercers, i no has d&#x27;obrir un repositori auxiliar només per un entrypoint de poques línies.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;Go&lt;&#x2F;code&gt; i &lt;code&gt;Rust&lt;&#x2F;code&gt; continuen sent opcions perfectament bones i vàlides per això.
I si tens shell disponible, un script encara pot ser suficient en casos simples.
Però en un entorn on ja tens &lt;code&gt;dotnet-10-sdk&lt;&#x2F;code&gt; al build i vols un binari Native AOT petit i autocontingut, C# passa de ser una opció curiosa a ser probablement la més convenient.&lt;&#x2F;p&gt;






&lt;div class=&quot;character-note character-hooded character-comment character-right&quot;&gt;
    &lt;div class=&quot;character-avatar&quot;&gt;
        
            &lt;img src=&quot;https:&#x2F;&#x2F;eudald.gr&#x2F;images&#x2F;characters&#x2F;hooded.png&quot;
                 alt=&quot;hooded&quot;
                 width=&quot;80&quot;
                 height=&quot;80&quot; &#x2F;&gt;
        
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;character-content&quot;&gt;
        &lt;div class=&quot;character-bubble&quot;&gt;
            &lt;p&gt;No dic que sigui l&#x27;única resposta bona.
Dic que, si ja vius dins l&#x27;ecosistema .NET, ara tens una resposta molt pragmàtica.&lt;&#x2F;p&gt;

        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;tancament&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#tancament&quot; aria-label=&quot;Anchor link for: tancament&quot;&gt;Tancament&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;La novetat de single-file C# a .NET 10 és fàcil de vendre com una millora de DX.
Però crec que el més interessant és una altra cosa: obre la porta a un scripting &quot;seriós&quot; amb C#, prou simple per a tasques petites i prou sòlid per acabar a producció.&lt;&#x2F;p&gt;
&lt;p&gt;En aquest cas, no estem parlant d&#x27;un hello world.
Estem parlant d&#x27;un entrypoint Native AOT per a una imatge rootless, distroless i sense shell.
I això, sincerament, em sembla un use-case molt millor que qualsevol demo.&lt;&#x2F;p&gt;
&lt;p&gt;Si vols veure l&#x27;exemple complet, amb &lt;code&gt;entrypoint.cs&lt;&#x2F;code&gt;, &lt;code&gt;melange.yaml&lt;&#x2F;code&gt; i &lt;code&gt;apko.yaml&lt;&#x2F;code&gt;, aquí el tens: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;vegops&#x2F;containers&#x2F;tree&#x2F;main&#x2F;qbittorrent&quot;&gt;vegops&#x2F;containers qBittorrent&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
