<?xml version="1.0" encoding="UTF-8"?>
<rss  xmlns:atom="http://www.w3.org/2005/Atom" 
      xmlns:media="http://search.yahoo.com/mrss/" 
      xmlns:content="http://purl.org/rss/1.0/modules/content/" 
      xmlns:dc="http://purl.org/dc/elements/1.1/" 
      version="2.0">
<channel>
<title>Produnis</title>
<link>https://www.produnis.de/blog/</link>
<atom:link href="https://www.produnis.de/blog/index.xml" rel="self" type="application/rss+xml"/>
<description></description>
<generator>quarto-1.7.32</generator>
<lastBuildDate>Fri, 11 Jul 2025 19:19:00 GMT</lastBuildDate>
<item>
  <title>Wie man Tabellen oder Bilder über beide Spalten im Typst-Zweispaltenlayout anzeigt (Quarto + Typst)</title>
  <dc:creator>Joe Slam</dc:creator>
  <link>https://www.produnis.de/blog/posts/2025-07-11-typst-span-over-two-column/</link>
  <description><![CDATA[ 





<p>Ich nutze Quarto, um wissenschaftliche Artikel zu schreiben, und exportiere das Ergebnis als PDF mit Typst. Mein Layout ist dabei zweispaltig, was ich in meinem Typst-Template wie folgt aktiviere:</p>
<p><code>show: columns.with(2)</code></p>
<p>Manchmal möchte ich jedoch sehr breite Tabellen oder Bilder einfügen, die sich über beide Spalten erstrecken sollen.</p>
<p>In Typst selbst lässt sich das mit dem <code>place</code>-Befehl lösen:</p>
<p><code>#place(top+center, scope: "parent", float: true)[INHALT]</code></p>
<p>In Quarto kann man das umsetzen, indem man manuell zwei Typst-Codeblöcke (typst-Chunks) um den Inhalt legt – z. B. um eine Tabelle:</p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource markdown number-lines code-with-copy"><code class="sourceCode markdown"><span id="cb1-1"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{=typst}</span></span>
<span id="cb1-2"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#place(top+center, scope: "parent", float: true)[</span></span>
<span id="cb1-3"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span>
<span id="cb1-4"></span>
<span id="cb1-5"></span>
<span id="cb1-6"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span> **Default** | **Left** | **Right** | **Center** | **Default** | **Left** | **Right** | **Center** <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span></span>
<span id="cb1-7"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|:-----------|:--------|---------:|:--------:|:-----------|:--------|---------:|:--------:|</span></span>
<span id="cb1-8"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span> 12         <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span> 12      <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span> 12       <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span> 12       <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span> 12         <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span> 12      <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span> 12       <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span> 12       <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span></span>
<span id="cb1-9"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span> 123        <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span> 123     <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span> 123      <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span> 123      <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span> 123        <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span> 123     <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span> 123      <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span> 123      <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span></span>
<span id="cb1-10"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span> 1          <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span> 1       <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span> 1        <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span> 1        <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span> 1          <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span> 1       <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span> 1        <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span> 1        <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">|</span></span>
<span id="cb1-11"></span>
<span id="cb1-12">: Tolle Tabelle {#tbl-mulitcolumn1}</span>
<span id="cb1-13"></span>
<span id="cb1-14"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{=typst}</span></span>
<span id="cb1-15"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">]</span></span>
<span id="cb1-16"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span></code></pre></div>
<p>Das funktioniert, ist aber nicht wirklich „the Quarto way“.</p>
<section id="lua-filter" class="level2">
<h2 class="anchored" data-anchor-id="lua-filter">Lua-Filter</h2>
<p>Um das eleganter zu lösen, habe ich einen kleinen Lua-Filter geschrieben (<code>multicolumn.lua</code>), der automatisch jede <code>::: {.multicolumn}</code>-Umgebung in den passenden <code>#place(...)</code>-Befehl für Typst übersetzt:</p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource {lua} number-lines code-with-copy"><code class="sourceCode"><span id="cb2-1">function Div(div)</span>
<span id="cb2-2">  if div.classes:includes("multicolumn") then</span>
<span id="cb2-3">    local typst_start = pandoc.RawBlock("typst", '#place(top+center, scope: "parent", float: true)[')</span>
<span id="cb2-4">    local typst_end = pandoc.RawBlock("typst", ']')</span>
<span id="cb2-5"></span>
<span id="cb2-6">    local result = {typst_start}</span>
<span id="cb2-7">    for _, el in ipairs(div.content) do</span>
<span id="cb2-8">      table.insert(result, el)</span>
<span id="cb2-9">    end</span>
<span id="cb2-10">    table.insert(result, typst_end)</span>
<span id="cb2-11">    return result</span>
<span id="cb2-12">  end</span>
<span id="cb2-13">end</span></code></pre></div>
<p>Den Filter aktiviere ich im YAML-Header wie folgt:</p>
<div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource {yaml} number-lines code-with-copy"><code class="sourceCode"><span id="cb3-1">      filters:</span>
<span id="cb3-2">        - multicolumn.lua</span></code></pre></div>
<p>Dann kann ich im Markdown einfach folgende Struktur verwenden:</p>
<div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource {markdown} number-lines code-with-copy"><code class="sourceCode"><span id="cb4-1"></span>
<span id="cb4-2">:::{.multicolumn}</span>
<span id="cb4-3"></span>
<span id="cb4-4">| **Default** | **Left** | **Right** | **Center** | **Default** | **Left** | **Right** | **Center** |</span>
<span id="cb4-5">|:-----------|:--------|---------:|:--------:|:-----------|:--------|---------:|:--------:|</span>
<span id="cb4-6">| 12         | 12      | 12       | 12       | 12         | 12      | 12       | 12       |</span>
<span id="cb4-7">| 123        | 123     | 123      | 123      | 123        | 123     | 123      | 123      |</span>
<span id="cb4-8">| 1          | 1       | 1        | 1        | 1          | 1       | 1        | 1        |</span>
<span id="cb4-9"></span>
<span id="cb4-10">: My span table {#tbl-span2}</span>
<span id="cb4-11"></span>
<span id="cb4-12">:::</span>
<span id="cb4-13"></span></code></pre></div>
<p>Das Ergebnis: Die Tabelle erscheint über beide Spalten hinweg, ganz ohne manuelle Typst-Blöcke. Das funktioniert genauso gut auch mit Bildern oder R-Code-Chunks.</p>
</section>
<section id="typsttabellen-direkt-spannen" class="level2">
<h2 class="anchored" data-anchor-id="typsttabellen-direkt-spannen">Typsttabellen direkt spannen</h2>
<p>Markdowntabellen sind in ihren Manipulationsmöglichkeiten stark eingeschränkt. Sie können z.B. kein <code>colspan</code>, keine Farben und keine Strichmodifikationen; Typst hingegen schon. Und so kann es bei aufwendigen Tabellen eine praktikable Lösung sein, direkt den Typst-Code zu verwenden.</p>
<p>Damit diese Tabelle per crossref referenziert werden kann, sollte die in Quarto integrierte Tabellenumgebung verwendet werden:</p>
<div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource markdown number-lines code-with-copy"><code class="sourceCode markdown"><span id="cb5-1">:::{#tbl-REFERENZLABEL}</span>
<span id="cb5-2"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{=typst}</span></span>
<span id="cb5-3"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#table( TOLLE TYPST TABELLE )</span></span>
<span id="cb5-4"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span>
<span id="cb5-5"></span>
<span id="cb5-6">BESCHRIFTUNG</span>
<span id="cb5-7">:::</span></code></pre></div>
<p>Die Tabelle kann jetzt per <code>@tbl-REFERENZLABEL</code> referenziert werden.</p>
<p>Damit diese aufwendig gestalteten Typsttabellen auch über beide Spalten gespannt werden, wickeln wir das Ganze in die oben erstellte <code>.mulitcolumn</code> Umgebung:</p>
<div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode numberSource markdown number-lines code-with-copy"><code class="sourceCode markdown"><span id="cb6-1">::::{.multicolumn}</span>
<span id="cb6-2">:::{#tbl-REFERENZALBEL}</span>
<span id="cb6-3"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```{=typst}</span></span>
<span id="cb6-4"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#table( TOLLE TYPST TABELLE )</span></span>
<span id="cb6-5"><span class="in" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">```</span></span>
<span id="cb6-6"></span>
<span id="cb6-7">BESCHRIFTUNG</span>
<span id="cb6-8">:::</span>
<span id="cb6-9">::::</span></code></pre></div>
<p>Viel Spass beim Coden!</p>
</section>
<section id="weblinks" class="level2">
<h2 class="anchored" data-anchor-id="weblinks">Weblinks</h2>
<ul>
<li><a href="https://quarto.org/" class="uri">https://quarto.org/</a></li>
<li><a href="https://typst.app" class="uri">https://typst.app</a></li>
<li><a href="https://github.com/quarto-dev/quarto-cli/discussions/13065" class="uri">https://github.com/quarto-dev/quarto-cli/discussions/13065</a></li>
</ul>
            <br><center>
            <div class="matrixfoot" id="matrixfooter">
            <a href="https://matrix.to/#/#produnis-blog:tchncs.de">
            <img src="https://www.produnis.de/images/Matrix.webp" width="60">
            </a>
            Diskussion per Matrix unter <a href="https://matrix.to/#/#produnis-blog:tchncs.de">https://matrix.to/#/#produnis-blog:tchncs.de</a>
            </div>
            </center><br>&nbsp;
        


</section>

 ]]></description>
  <category>quarto</category>
  <category>typst</category>
  <category>ubuntuusers</category>
  <guid>https://www.produnis.de/blog/posts/2025-07-11-typst-span-over-two-column/</guid>
  <pubDate>Fri, 11 Jul 2025 19:19:00 GMT</pubDate>
  <media:content url="https://www.produnis.de/images/logos/typst.png" medium="image" type="image/png" height="144" width="144"/>
</item>
<item>
  <title>Eigene Wörterliste für KHangMan</title>
  <dc:creator>Joe Slam</dc:creator>
  <link>https://www.produnis.de/blog/posts/2025-07-03-khangman-wordlist/</link>
  <description><![CDATA[ 





<p>KHangMan ist ein KDE-App, die auf dem klassischen Galgenmännchen-Spiel basiert. Sie ist Teil der KDE Software Compilation, genauer gesagt, des <code>kdeedu</code>-Pakets.</p>
<p>KHangMan funktioniert dabei nicht so, wie ihr vielleicht denkt. Denn die Wörter, die erraten werden sollen, können nicht selbst eingegeben werden. Vielmehr greift KHangMan auf eine Reihe von vorinstallierten <em>Wortlisten</em> zurück, die für verschiedene Kategorien bereitgestellt werden, z.B. “Zahlen”, “Hauptstädte”, “Tiere”, usw.</p>
<p>Möchte man eigene Wörter spielen, muss man eine eigene Wortliste erstellen und für KHangMan verfügbar machen.</p>
<section id="custom-word-list" class="level2">
<h2 class="anchored" data-anchor-id="custom-word-list">custom word list</h2>
<p>Die Wörterlisten liegen im Verzeichnis <code>/usr/share/apps/kvtml/LANGUAE</code>, wobei <code>LANGUAGE</code> durch den Ländercode ersetzt werden muss. Die deutschen Wörterlisten liegen also unter <code>/usr/share/apps/kvtml/de</code> und haben die Dateiendung <code>.kvtml</code>. Für jede Wörterliste existiert eine eigene <code>.kvtml</code>-Datei.</p>
<p>Die Skelettstruktur einer solchen Wörterliste sieht so aus:</p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource {xml} number-lines code-with-copy"><code class="sourceCode"><span id="cb1-1">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span>
<span id="cb1-2">&lt;!DOCTYPE kvtml PUBLIC "kvtml2.dtd" "http://edu.kde.org/kvtml/kvtml2.dtd"&gt;</span>
<span id="cb1-3">&lt;kvtml version="2.0"&gt;</span>
<span id="cb1-4">  &lt;information&gt;</span>
<span id="cb1-5">    &lt;generator&gt;converter&lt;/generator&gt;</span>
<span id="cb1-6">    &lt;title&gt;TITEL DER LISTE&lt;/title&gt;</span>
<span id="cb1-7">    &lt;comment&gt;DEINE BESCHREIBUNG&lt;/comment&gt;</span>
<span id="cb1-8">  &lt;/information&gt;</span>
<span id="cb1-9"></span>
<span id="cb1-10">  &lt;identifiers&gt;</span>
<span id="cb1-11">    &lt;identifier id="0"&gt;</span>
<span id="cb1-12">      &lt;locale&gt;de&lt;/locale&gt;</span>
<span id="cb1-13">    &lt;/identifier&gt;</span>
<span id="cb1-14">  &lt;/identifiers&gt;</span>
<span id="cb1-15">  </span>
<span id="cb1-16">  &lt;entries&gt;</span>
<span id="cb1-17">  </span>
<span id="cb1-18">    &lt;entry id="0"&gt;</span>
<span id="cb1-19">      &lt;inactive&gt;false&lt;/inactive&gt;</span>
<span id="cb1-20">      &lt;inquery&gt;false&lt;/inquery&gt;</span>
<span id="cb1-21">      &lt;translation id="0"&gt;</span>
<span id="cb1-22">        &lt;text&gt;DEIN WORT&lt;/text&gt;</span>
<span id="cb1-23">        &lt;comment&gt;EIN KOMMENTAR&lt;/comment&gt;</span>
<span id="cb1-24">      &lt;/translation&gt;</span>
<span id="cb1-25">    &lt;/entry&gt;</span>
<span id="cb1-26"></span>
<span id="cb1-27">    &lt;/entries&gt;</span>
<span id="cb1-28">&lt;/kvtml&gt;</span></code></pre></div>
<ul>
<li>in Zeile 6 und 7 wird der Name der Liste samt einer kleinen Beschreibung angegeben. Unter diesem Namen ist die Wortliste später in KHangMan auffindbar.</li>
<li>in Zeile 12 geben wir an, dass die Sprache der Liste <code>de</code> ist.</li>
<li>Die Zeilen 18 bis 25 bilden einen Entry-Block für ein gewünschtes Wort. Dabei wird
<ul>
<li>in Zeile 18 eine eindeutige <code>&lt;entry id&gt;</code> angegeben (hochzählen)</li>
<li>in Zeile 22 das eigentliche Wort definiert</li>
<li>in Zeile 23 ein kurzer Hilfetext gesetzt.</li>
</ul></li>
<li>diese Entry-Blöcke müssen für jedes Wort erzeugt werden.</li>
</ul>
<p>Für ein Statistik-Quiz könnte die vollständige Datei so aussehen:</p>
<p><code>sudo nano /usr/share/apps/kvtml/statistikquiz.kvtml</code></p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource {xml} number-lines code-with-copy"><code class="sourceCode"><span id="cb2-1">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span>
<span id="cb2-2">&lt;!DOCTYPE kvtml PUBLIC "kvtml2.dtd" "http://edu.kde.org/kvtml/kvtml2.dtd"&gt;</span>
<span id="cb2-3">&lt;kvtml version="2.0"&gt;</span>
<span id="cb2-4">  &lt;information&gt;</span>
<span id="cb2-5">    &lt;generator&gt;converter&lt;/generator&gt;</span>
<span id="cb2-6">    &lt;title&gt;Statistik&lt;/title&gt;</span>
<span id="cb2-7">    &lt;comment&gt;Statistik&lt;/comment&gt;</span>
<span id="cb2-8">  &lt;/information&gt;</span>
<span id="cb2-9">  &lt;identifiers&gt;</span>
<span id="cb2-10">    &lt;identifier id="0"&gt;</span>
<span id="cb2-11">      &lt;locale&gt;de&lt;/locale&gt;</span>
<span id="cb2-12">    &lt;/identifier&gt;</span>
<span id="cb2-13">  &lt;/identifiers&gt;</span>
<span id="cb2-14">  &lt;entries&gt;</span>
<span id="cb2-15">    &lt;entry id="0"&gt;</span>
<span id="cb2-16">      &lt;inactive&gt;false&lt;/inactive&gt;</span>
<span id="cb2-17">      &lt;inquery&gt;false&lt;/inquery&gt;</span>
<span id="cb2-18">      &lt;translation id="0"&gt;</span>
<span id="cb2-19">        &lt;text&gt;Boxplot&lt;/text&gt;</span>
<span id="cb2-20">        &lt;comment&gt;graphische Darstellung einer metrischen Werteverteilung&lt;/comment&gt;</span>
<span id="cb2-21">      &lt;/translation&gt;</span>
<span id="cb2-22">    &lt;/entry&gt;</span>
<span id="cb2-23">    &lt;entry id="1"&gt;</span>
<span id="cb2-24">      &lt;inactive&gt;false&lt;/inactive&gt;</span>
<span id="cb2-25">      &lt;inquery&gt;false&lt;/inquery&gt;</span>
<span id="cb2-26">      &lt;translation id="0"&gt;</span>
<span id="cb2-27">        &lt;text&gt;Histogram&lt;/text&gt;</span>
<span id="cb2-28">        &lt;comment&gt;graphische Darstellung klassierter Häufigkeiten&lt;/comment&gt;</span>
<span id="cb2-29">      &lt;/translation&gt;</span>
<span id="cb2-30">    &lt;/entry&gt;</span>
<span id="cb2-31">    &lt;entry id="2"&gt;</span>
<span id="cb2-32">      &lt;inactive&gt;false&lt;/inactive&gt;</span>
<span id="cb2-33">      &lt;inquery&gt;false&lt;/inquery&gt;</span>
<span id="cb2-34">      &lt;translation id="0"&gt;</span>
<span id="cb2-35">        &lt;text&gt;Kausalität&lt;/text&gt;</span>
<span id="cb2-36">        &lt;comment&gt;ursächlicher Zusammenhang&lt;/comment&gt;</span>
<span id="cb2-37">      &lt;/translation&gt;</span>
<span id="cb2-38">    &lt;/entry&gt;</span>
<span id="cb2-39">    &lt;entry id="3"&gt;</span>
<span id="cb2-40">      &lt;inactive&gt;false&lt;/inactive&gt;</span>
<span id="cb2-41">      &lt;inquery&gt;false&lt;/inquery&gt;</span>
<span id="cb2-42">      &lt;translation id="0"&gt;</span>
<span id="cb2-43">        &lt;text&gt;Konfidenzintervall&lt;/text&gt;</span>
<span id="cb2-44">        &lt;comment&gt;Sicherheitsbereich&lt;/comment&gt;</span>
<span id="cb2-45">      &lt;/translation&gt;</span>
<span id="cb2-46">    &lt;/entry&gt;</span>
<span id="cb2-47">    &lt;entry id="4"&gt;</span>
<span id="cb2-48">      &lt;inactive&gt;false&lt;/inactive&gt;</span>
<span id="cb2-49">      &lt;inquery&gt;false&lt;/inquery&gt;</span>
<span id="cb2-50">      &lt;translation id="0"&gt;</span>
<span id="cb2-51">        &lt;text&gt;Korrelation&lt;/text&gt;</span>
<span id="cb2-52">        &lt;comment&gt;Zusammenhang (aber nicht kausal)&lt;/comment&gt;</span>
<span id="cb2-53">      &lt;/translation&gt;</span>
<span id="cb2-54">    &lt;/entry&gt;</span>
<span id="cb2-55">    &lt;entry id="5"&gt;</span>
<span id="cb2-56">      &lt;inactive&gt;false&lt;/inactive&gt;</span>
<span id="cb2-57">      &lt;inquery&gt;false&lt;/inquery&gt;</span>
<span id="cb2-58">      &lt;translation id="0"&gt;</span>
<span id="cb2-59">        &lt;text&gt;Regressionsgerade&lt;/text&gt;</span>
<span id="cb2-60">        &lt;comment&gt;Wird beschrieben mit y=a+bx&lt;/comment&gt;</span>
<span id="cb2-61">      &lt;/translation&gt;</span>
<span id="cb2-62">    &lt;/entry&gt;</span>
<span id="cb2-63">    &lt;entry id="6"&gt;</span>
<span id="cb2-64">      &lt;inactive&gt;false&lt;/inactive&gt;</span>
<span id="cb2-65">      &lt;inquery&gt;false&lt;/inquery&gt;</span>
<span id="cb2-66">      &lt;translation id="0"&gt;</span>
<span id="cb2-67">        &lt;text&gt;Signifikanz&lt;/text&gt;</span>
<span id="cb2-68">        &lt;comment&gt;liegt vor wenn p kleiner alpha ist&lt;/comment&gt;</span>
<span id="cb2-69">      &lt;/translation&gt;</span>
<span id="cb2-70">    &lt;/entry&gt;</span>
<span id="cb2-71">    &lt;entry id="7"&gt;</span>
<span id="cb2-72">      &lt;inactive&gt;false&lt;/inactive&gt;</span>
<span id="cb2-73">      &lt;inquery&gt;false&lt;/inquery&gt;</span>
<span id="cb2-74">      &lt;translation id="0"&gt;</span>
<span id="cb2-75">        &lt;text&gt;Standardabweichung&lt;/text&gt;</span>
<span id="cb2-76">        &lt;comment&gt;Wurzel aus der Varianz&lt;/comment&gt;</span>
<span id="cb2-77">      &lt;/translation&gt;</span>
<span id="cb2-78">    &lt;/entry&gt;</span>
<span id="cb2-79">    &lt;entry id="8"&gt;</span>
<span id="cb2-80">      &lt;inactive&gt;false&lt;/inactive&gt;</span>
<span id="cb2-81">      &lt;inquery&gt;false&lt;/inquery&gt;</span>
<span id="cb2-82">      &lt;translation id="0"&gt;</span>
<span id="cb2-83">        &lt;text&gt;Varianz&lt;/text&gt;</span>
<span id="cb2-84">        &lt;comment&gt;Quadrat der Standardabweichung&lt;/comment&gt;</span>
<span id="cb2-85">      &lt;/translation&gt;</span>
<span id="cb2-86">    &lt;/entry&gt;</span>
<span id="cb2-87">  &lt;/entries&gt;</span>
<span id="cb2-88">&lt;/kvtml&gt;</span></code></pre></div>
<p>Nachdem die Datei gespeichert ist, wird KHangMan gestartet.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.produnis.de/blog/posts/2025-07-03-khangman-wordlist/khangman1.webp" class="img-fluid figure-img"></p>
<figcaption>Wordlist wechseln</figcaption>
</figure>
</div>
<p>Unten links wird die derzeit aktive Wörterliste angezeigt. In meinem Beispiel ist das “<em>Tiere</em>”.</p>
<p>Wenn man darauf klickt, kann eine andere Wörterliste ausgewählt werden. Da meine Systemsprache deutsch ist, sucht KHangMan im Ordner <code>/usr/share/apps/kvtml/de</code> nach validen <code>.kvtml</code>-Dateien.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.produnis.de/blog/posts/2025-07-03-khangman-wordlist/khangman2.webp" class="img-fluid figure-img"></p>
<figcaption>eigene Wordlist auswählen</figcaption>
</figure>
</div>
<p>Hier sollte - wenn alles richtig gemacht wurde - die neue eigene Liste auftauchen.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.produnis.de/blog/posts/2025-07-03-khangman-wordlist/khangman3.webp" class="img-fluid figure-img"></p>
<figcaption>Erstes Wort von der Liste</figcaption>
</figure>
</div>
<p>Ist diese ausgewählt, kann das Spiel beginnen.</p>
<p>:=)</p>
</section>
<section id="python-script" class="level2">
<h2 class="anchored" data-anchor-id="python-script">Python-Script</h2>
<p>Unter Umständen kann es mühsam sein, eine oder mehrere solcher <code>.kvtml</code>-Dateien zu erstellen und zu pflegen. Beispielsweise ist es mühselig, die <code>entry id</code> nachzuverfolgen, wenn ein Entry-Block zwischen bestehende Blöcke eingeschoben werden soll.</p>
<p>Daher hab ich mir ein kleines naives Python-Script geschrieben, welches mir die Arbeit etwas erleichtert.</p>
<p>Das Script nimmt eine Textdatei entgegen, und erzeugt daraus die passende <code>.kvtml</code>-Datei.</p>
<p>Für das Statistikquiz sieht die Datei so aus:</p>
<p><code>nano statistik.txt</code></p>
<pre><code>Boxplot       graphische Darstellung einer metrischen Werteverteilung
Histogram       graphische Darstellung klassierter Häufigkeiten
Kausalität         ursächlicher Zusammenhang
Konfidenzintervall         Sicherheitsbereich
Korrelation        Zusammenhang (aber nicht kausal)
Regressionsgerade        Wird beschrieben mit y=a+bx
Signifikanz        liegt vor wenn p kleiner alpha ist
Standardabweichung       Wurzel aus der Varianz
Varianz        Quadrat der Standardabweichung
</code></pre>
<p>Jede Zeile repräsentiert einen Worteintrag. Zuerst kommt das gesuchte Wort, dann mindestens 2 Leerzeichen, und anschließend der Hinweistext.</p>
<p>Hier nun das Python-Script, welches diese Datei ausliest</p>
<p><code>nano create-wordlist.py</code></p>
<div id="729f4cdd" class="cell" data-execution_count="1">
<div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#!/usr/bin/env python3</span></span>
<span id="cb4-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> sys</span>
<span id="cb4-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> re</span>
<span id="cb4-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> xml.etree.ElementTree <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> ET</span>
<span id="cb4-5"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> xml.dom <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> minidom</span>
<span id="cb4-6"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> string</span>
<span id="cb4-7"></span>
<span id="cb4-8"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> prettify(elem):</span>
<span id="cb4-9">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Return a pretty-printed XML string for the Element."""</span></span>
<span id="cb4-10">    rough_string <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ET.tostring(elem, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'utf-8'</span>)</span>
<span id="cb4-11">    parsed <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> minidom.parseString(rough_string)</span>
<span id="cb4-12">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> parsed.toprettyxml(indent<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"  "</span>)</span>
<span id="cb4-13"></span>
<span id="cb4-14"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> sanitize_filename(name):</span>
<span id="cb4-15">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Sanitize the title to create a safe filename."""</span></span>
<span id="cb4-16">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Entfernt alle Zeichen außer Buchstaben, Zahlen, Bindestrich und Unterstrich</span></span>
<span id="cb4-17">    valid_chars <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"-_.() </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>string<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>ascii_letters<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}{</span>string<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>digits<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb4-18">    sanitized <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span>.join(c <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> c <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> valid_chars <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'_'</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> c <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> name)</span>
<span id="cb4-19">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> sanitized.replace(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">' '</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'_'</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">".kvtml"</span></span>
<span id="cb4-20"></span>
<span id="cb4-21"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> main():</span>
<span id="cb4-22">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(sys.argv) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>:</span>
<span id="cb4-23">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Usage: python3 generate_kvtml.py input.txt title comment"</span>)</span>
<span id="cb4-24">        sys.exit(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb4-25"></span>
<span id="cb4-26">    input_file <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sys.argv[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb4-27">    title <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sys.argv[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]</span>
<span id="cb4-28">    comment <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sys.argv[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>]</span>
<span id="cb4-29">    output_file <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sanitize_filename(title)</span>
<span id="cb4-30"></span>
<span id="cb4-31">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">open</span>(input_file, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r"</span>, encoding<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"utf-8"</span>) <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> f:</span>
<span id="cb4-32">        lines <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [line.strip() <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> line <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> f <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> line.strip()]</span>
<span id="cb4-33"></span>
<span id="cb4-34">    kvtml <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ET.Element(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"kvtml"</span>, version<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"2.0"</span>)</span>
<span id="cb4-35"></span>
<span id="cb4-36">    info <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ET.SubElement(kvtml, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"information"</span>)</span>
<span id="cb4-37">    ET.SubElement(info, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"generator"</span>).text <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"converter"</span></span>
<span id="cb4-38">    ET.SubElement(info, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"title"</span>).text <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> title</span>
<span id="cb4-39">    ET.SubElement(info, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"comment"</span>).text <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> comment</span>
<span id="cb4-40"></span>
<span id="cb4-41">    identifiers <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ET.SubElement(kvtml, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"identifiers"</span>)</span>
<span id="cb4-42">    identifier <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ET.SubElement(identifiers, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"identifier"</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"0"</span>)</span>
<span id="cb4-43">    ET.SubElement(identifier, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"locale"</span>).text <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"de"</span></span>
<span id="cb4-44"></span>
<span id="cb4-45">    entries <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ET.SubElement(kvtml, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"entries"</span>)</span>
<span id="cb4-46"></span>
<span id="cb4-47">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> idx, line <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(lines):</span>
<span id="cb4-48">        parts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> re.split(<span class="vs" style="color: #20794D;
background-color: null;
font-style: inherit;">r'</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\t</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span><span class="vs" style="color: #20794D;
background-color: null;
font-style: inherit;"> </span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{2,}</span><span class="vs" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>, line)</span>
<span id="cb4-49">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(parts) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>:</span>
<span id="cb4-50">            <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Warning: Skipping invalid line </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>idx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>line<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb4-51">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">continue</span></span>
<span id="cb4-52">        text, comment_text <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> parts</span>
<span id="cb4-53">        entry <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ET.SubElement(entries, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"entry"</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>(idx))</span>
<span id="cb4-54">        ET.SubElement(entry, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"inactive"</span>).text <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"false"</span></span>
<span id="cb4-55">        ET.SubElement(entry, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"inquery"</span>).text <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"false"</span></span>
<span id="cb4-56">        trans <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ET.SubElement(entry, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"translation"</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"0"</span>)</span>
<span id="cb4-57">        ET.SubElement(trans, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"text"</span>).text <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> text</span>
<span id="cb4-58">        ET.SubElement(trans, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"comment"</span>).text <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> comment_text</span>
<span id="cb4-59"></span>
<span id="cb4-60">    pretty_xml <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> prettify(kvtml)</span>
<span id="cb4-61"></span>
<span id="cb4-62">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">open</span>(output_file, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"w"</span>, encoding<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"utf-8"</span>) <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> f:</span>
<span id="cb4-63">        f.write(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>)</span>
<span id="cb4-64">        f.write(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'&lt;!DOCTYPE kvtml PUBLIC "kvtml2.dtd" "http://edu.kde.org/kvtml/kvtml2.dtd"&gt;</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>)</span>
<span id="cb4-65">        f.write(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>.join(pretty_xml.split(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>)[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>:]))</span>
<span id="cb4-66"></span>
<span id="cb4-67">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"✅ KVTML-Datei wurde geschrieben: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>output_file<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span>
<span id="cb4-68"></span>
<span id="cb4-69"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">__name__</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"__main__"</span>:</span>
<span id="cb4-70">    main()</span></code></pre></div>
</div>
<p>Das Script wird ausführbar gemacht mittels</p>
<p><code>chmod +x create-wordlist.py</code></p>
<p>…und aufgerufen per:</p>
<p><code>./create-wordlist.py TEXTDATEI LISTENNAME BESCHREIBUNG</code></p>
<p>Im Falle des Statistikquiz lautet der Aufruf</p>
<p><code>./create-wordlist.py statistik.txt Statistik Grundbegriffe</code></p>
<p>Das Script erzeugt die Datei <code>LISTENNAME.kvtml</code>, also in unserem Falle <code>Statistik.kvtml</code>, welche alle Entry-Blöcke der Wörterliste enthält. Diese kann nun ins <code>kvtml</code>-Verzeichnis kopiert werden.</p>
<p><code>cp Statistik.kvtml /usr/share/apps/kvtml/de/</code></p>
<p>Viel Spass beim Ausprobieren!</p>
</section>
<section id="weblinks" class="level2">
<h2 class="anchored" data-anchor-id="weblinks">Weblinks</h2>
<ul>
<li><a href="https://apps.kde.org/khangman/" class="uri">https://apps.kde.org/khangman/</a></li>
<li><a href="https://apps.kde.org/education/khangman/tutorials/khangman-addwords.pdf" class="uri">https://apps.kde.org/education/khangman/tutorials/khangman-addwords.pdf</a></li>
</ul>
            <br><center>
            <div class="matrixfoot" id="matrixfooter">
            <a href="https://matrix.to/#/#produnis-blog:tchncs.de">
            <img src="https://www.produnis.de/images/Matrix.webp" width="60">
            </a>
            Diskussion per Matrix unter <a href="https://matrix.to/#/#produnis-blog:tchncs.de">https://matrix.to/#/#produnis-blog:tchncs.de</a>
            </div>
            </center><br>&nbsp;
        


</section>

 ]]></description>
  <category>Professor Hastig</category>
  <category>KDE</category>
  <category>Python</category>
  <category>ubuntuusers</category>
  <guid>https://www.produnis.de/blog/posts/2025-07-03-khangman-wordlist/</guid>
  <pubDate>Thu, 03 Jul 2025 20:53:00 GMT</pubDate>
  <media:content url="https://www.produnis.de/images/logos/kde.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Berechnung des Luftwiderstands fahrender Fahrzeuge in ruhender Luft</title>
  <dc:creator>Opa Jupp</dc:creator>
  <link>https://www.produnis.de/blog/posts/2025-03-25-luftwiderstand/</link>
  <description><![CDATA[ 





<p>Ein fahrender Pkw zum Beispiel, der in Fahrtrichtung schneller unterwegs ist als die ihn umgebende Luft, “sieht sich” in dieser Situation einem Strömungswiderstand ausgesetzt, der eine bremsende Wirkung hat. Bei Windstille tritt der Bremseffekt immer auf, weil eine Relativbewegung zwischen dem Fahrzeug und der Luft dann nur gegeneinander stattfindet und zudem die Eigengeschwindigkeit des Gefährts unabhängig von der Bewegungsrichtung sowie bei Vorwärts- und Rückwärtsfahrt stets mit seiner Relativgeschwindigkeit zur Luft identisch ist. Von der vereinfachenden Annahme einer ruhenden Luft wird bei allen folgenden Berechnungen ausgegangen. Als Formelzeichen werden dabei verwendet:</p>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?v"> für die Eigengeschwindigkeit des betrachteten Fahrzeugs, mit der dieses umgekehrt von der ruhenden Luft angeströmt wird,<br>
</li>
<li><img src="https://latex.codecogs.com/png.latex?A"> für die durch Projektion ermittelte größte Querschnittsfläche des Fahrzeugs und</li>
<li><img src="https://latex.codecogs.com/png.latex?%5Crho_%7BL%7D"> für die mittlere Dichte der erdnahen Luft.</li>
</ul>
<p>Darüber hinaus bezeichnen jeweils in Abhängigkeit von der Zeit <img src="https://latex.codecogs.com/png.latex?t">,</p>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?M_%7BL%7D"> die gegen das Fahrzeug strömende Luftmasse und</li>
<li><img src="https://latex.codecogs.com/png.latex?a"> deren Beschleunigung beim Aufprall.</li>
</ul>
<p>Gemäß dem zweiten Newtonschen Axiom - <strong>Kraft gleich Masse mal Beschleunigung</strong> - gilt für die als Bremskraft auf das Fahrzeug wirkende infinitesimale Beschleunigungskraft <img src="https://latex.codecogs.com/png.latex?dF_%7BL%7D"> einer infinitesimalen Luftmasse die Gleichung:</p>
<p><span id="eq-newton"><img src="https://latex.codecogs.com/png.latex?%0AdF_%7BL%7D(t)%20=%20%20%20dM_%7BL%7D(t)%20%5Ccdot%20a(t)%0A%5Ctag%7B1%7D"></span></p>
<p>Mit den Substitutionen:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AdM_%7BL%7D(t)%20=%20%5Crho_%7BL%7D%20%5Ccdot%20A%20%5Ccdot%20v(t)%20%5Ccdot%20dt%0A"></p>
<pre><code>   und       </code></pre>
<p><img src="https://latex.codecogs.com/png.latex?%0Aa(t)%20=%20%5Cfrac%7Bdv(t)%7D%7Bdt%7D%0A"></p>
<p>geht Gleichung&nbsp;1 über in die Form</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AdF_%7BL%7D(t)%20=%20%5Crho_%7BL%7D%20%5Ccdot%20A%20%5Ccdot%20v(t)%20%5Ccdot%20dt%20%5Ccdot%20%5Cfrac%7Bdv(t)%7D%7Bdt%7D%0A"></p>
<pre><code>    bzw.</code></pre>
<p><span id="eq-substitution"><img src="https://latex.codecogs.com/png.latex?%0AdF_%7BL%7D(v)%20=%20%5Crho_%7BL%7D%20%5Ccdot%20A%20%5Ccdot%20v%20%5Ccdot%20dv%0A%5Ctag%7B2%7D"></span></p>
<p>Da die ruhende Luft der Theorie nach im Bereich der Kollision mit dem betrachteten Fahrzeug auf dessen Geschwindigkeit hochbeschleunigt wird, ergibt sich aus Gleichung&nbsp;2 die wechselwirkende Gesamtkraft zwischen Gefährt und Luft zunächst zu:</p>
<p><span id="eq-impulsstrom"><img src="https://latex.codecogs.com/png.latex?%0AF_%7BL%7D(v)%20=%20%5Crho_%7BL%7D%20%5Ccdot%20A%20%5Ccdot%20%5Cint_%7B0%7D%5E%7Bv%7D%20v%20%5Ccdot%20dv%20=%20%5Cfrac%7B1%7D%7B2%7D%20%5Ccdot%20%5Crho_%7BL%7D%20%5Ccdot%20A%20%5Ccdot%20v%5E2%0A%5Ctag%7B3%7D"></span></p>
<p>(wird auch als Impulsstrom der Luft bezeichnet)</p>
<p>Für die Berechnung praxistauglicher Werte der Kraft <img src="https://latex.codecogs.com/png.latex?F_%7BL%7D"> - unter ihr versteht man gewöhnlich den Luftwiderstand eines Fahrzeugs - bedarf es in Gleichung&nbsp;3 noch der Einführung eines Korrekturfaktors, da reale Fahrzeuge in Bezug auf ihre Abbremsung durch die Luft nur grob angenähert durch ihre senkrecht im Luftstrom stehenden projizierten Querschnittsflächen repräsentiert werden können. Vor allem Pkw sind in der Regel besonders windschlüpfig bzw. windschnittig konstruiert und weisen deshalb meist deutlich kleinere Luftwiderstände auf, als sie Gleichung&nbsp;3 liefert. Realistische Werte für den Luftwiderstand ergeben sich nach Gleichung&nbsp;3, indem man deren rechte Seite mit einem experimentell zu ermittelnden dimensionslosen Faktor multipliziert, der die spezifischen aerodynamischen Eigenschaften eines Fahrzeugs berücksichtigt und allgemein als <img src="https://latex.codecogs.com/png.latex?c_%7BW%7D">-Wert (Luftwiderstandsbeiwert) bezeichnet wird. Die endgültig anzuwendende Formel für die Berechnung der Kraft, die von ruhender Luft auf einen sich darin mit der Eigengeschwindigkeit <img src="https://latex.codecogs.com/png.latex?v"> bewegenden Pkw oder Lkw entgegen deren Fahrtrichtung als Strömungswiderstand ausgeübt wird, lautet demnach</p>
<p><span id="eq-kraftformel"><img src="https://latex.codecogs.com/png.latex?%0AF_%7BL%7D(v)%20=%20%5Cfrac%7Bc_%7BW%7D%7D%7B2%7D%20%5Ccdot%20%5Crho_%7BL%7D%20%5Ccdot%20A%20%5Ccdot%20v%5E2%0A%5Ctag%7B4%7D"></span></p>
<p>In der Fachliteratur werden für Pkw <img src="https://latex.codecogs.com/png.latex?c_%7BW%7D">-Werte im Bereich von <img src="https://latex.codecogs.com/png.latex?0,2"> bis <img src="https://latex.codecogs.com/png.latex?0,4"> und für Lkw im Bereich von <img src="https://latex.codecogs.com/png.latex?0,5"> bis <img src="https://latex.codecogs.com/png.latex?0,85"> angegeben.</p>
            <br><center>
            <div class="matrixfoot" id="matrixfooter">
            <a href="https://matrix.to/#/#produnis-blog:tchncs.de">
            <img src="https://www.produnis.de/images/Matrix.webp" width="60">
            </a>
            Diskussion per Matrix unter <a href="https://matrix.to/#/#produnis-blog:tchncs.de">https://matrix.to/#/#produnis-blog:tchncs.de</a>
            </div>
            </center><br>&nbsp;
        



 ]]></description>
  <category>Professor Hastig</category>
  <guid>https://www.produnis.de/blog/posts/2025-03-25-luftwiderstand/</guid>
  <pubDate>Tue, 25 Mar 2025 19:10:00 GMT</pubDate>
  <media:content url="https://www.produnis.de/images/logos/thumbnail.png" medium="image" type="image/png" height="144" width="144"/>
</item>
<item>
  <title>Mit Ollama könnt ihr DeepSeek-R1 lokal laufen lassen</title>
  <dc:creator>Joe Slam</dc:creator>
  <link>https://www.produnis.de/blog/posts/2025-01-30-ollama/</link>
  <description><![CDATA[ 





<p>Mit dem Programm <code>Ollama</code> könnt ihr Large Language Models (LLMs) wie DeepSeek oder Mistral lokal auf eurem PC oder Laptop installieren und laufen lassen. Dabei nimmt euch <code>Ollama</code> die meiste Arbeit ab.</p>
<section id="installation" class="level2">
<h2 class="anchored" data-anchor-id="installation">Installation</h2>
<p>Unter <a href="https://ollama.com/download" class="uri">https://ollama.com/download</a> könnt ihr Versionen für macOS, Windoof und Linux herunterladen. Unter Archlinux erfolgt die Installation per</p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> pacman <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-S</span> ollama</span></code></pre></div>
<p>Wenn <code>Ollama</code> nicht in eurem Repository vorhanden ist, könnt ihr diesen Befehl verwenden:</p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">curl</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-fsSL</span> https://ollama.com/install.sh <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sh</span></span></code></pre></div>
<p>Nach der Installation kann <code>Ollama</code> per <code>systemd</code> gesteuert werden:</p>
<div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb3-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> systemctl enable ollama.service</span>
<span id="cb3-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> systemctl start ollama.service</span></code></pre></div>
</section>
<section id="speicherort-anpassen" class="level2">
<h2 class="anchored" data-anchor-id="speicherort-anpassen">Speicherort anpassen</h2>
<p>Um den Speicherort für die Modelle festzulegen, könnt ihr die Servicedatei <code>/etc/systemd/system/ollama.service</code> wie folgt anpassen (bei mir soll alles unter dem Pfad <code>/media/SILO/Ollama</code> abgelegt werden)</p>
<div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb4-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">[Unit]</span></span>
<span id="cb4-2"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">Description</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>Ollama <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Service</span></span>
<span id="cb4-3"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">After</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>network-online.target</span>
<span id="cb4-4"></span>
<span id="cb4-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">[Service]</span></span>
<span id="cb4-6"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">ExecStart</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>/usr/bin/ollama <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">serve</span></span>
<span id="cb4-7"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">WorkingDirectory</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>/media/SILO/Ollama</span>
<span id="cb4-8"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">Environment</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"HOME=/media/SILO/Ollama"</span></span>
<span id="cb4-9"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">Environment</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"OLLAMA_MODELS=/media/SILO/Ollama/models"</span></span>
<span id="cb4-10"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">User</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>ollama</span>
<span id="cb4-11"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">Group</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>ollama</span>
<span id="cb4-12"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">Restart</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>always</span>
<span id="cb4-13"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">RestartSec</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>3</span>
<span id="cb4-14"></span>
<span id="cb4-15"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">[Install]</span></span>
<span id="cb4-16"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">WantedBy</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>default.target</span></code></pre></div>
</section>
<section id="modelle-installieren" class="level2">
<h2 class="anchored" data-anchor-id="modelle-installieren">Modelle installieren</h2>
<p>Sobald <code>Ollama</code> gestartet ist, können die Modelle wie folgt installiert werden:</p>
<div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb5-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ollama</span> pull MODELLNAME</span></code></pre></div>
<p>Den <code>MODELLNAMEN</code> erhaltet ihr von der Ollama-Homepage <a href="https://ollama.com/search" class="uri">https://ollama.com/search</a>. Dort findet ihr das DeepSeek-R1-Modell unter <a href="https://ollama.com/library/deepseek-r1" class="uri">https://ollama.com/library/deepseek-r1</a>. Die Modelle sind jeweils in verschiedenen Varianten verfügbar, z.B. <code>1.5b</code>, <code>7b</code>, <code>14b</code>, <code>70b</code>. Hierbei handelt es sich um die Parameter, die das Modell verwendet (das <code>b</code> steht für Milliarden). Je kleiner die Zahl, desto “abgespeckter” ist die Version. Je größer die Zahl ist, desto krasser muss eure Hardware sein, damit das Modell nicht Tage benötigt, um zu antworten. Startet am besten mit der kleinsten Zahl, und wenn das gut läuft, dann nehmt die nächst höhere Zahl. Auf einem halbwegs aktuellem Laptop sollten die <code>7b</code>-Versionen gut laufen.</p>
<p>Ihr installiert das konkrete Modell, indem ihr die Variante per Doppelpunkt an den <code>MODELLNAMEN</code> anhängt. Für DeepSeek-R1 in der Variante <code>7b</code> lautet der Befehl:</p>
<div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb6-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ollama</span> pull deepseek-r1:7b</span></code></pre></div>
<p>Ihr könnt auch Modelle von HuggingFace verwenden, z.B. die <a href="https://huggingface.co/huihui-ai/DeepSeek-R1-Distill-Qwen-14B-abliterated-v2">abliterated Version von DeepSeek</a> von huihui:</p>
<div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb7-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ollama</span> pull huihui_ai/deepseek-r1-abliterated:14b</span></code></pre></div>
</section>
<section id="modell-benutzen" class="level2">
<h2 class="anchored" data-anchor-id="modell-benutzen">Modell benutzen</h2>
<p>Eine Übersicht eurer installierten Modelle erhaltet ihr mittels</p>
<div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb8-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ollama</span> list</span></code></pre></div>
<pre>NAME                                     ID              SIZE      MODIFIED       
deepseek-r1:7b                           0a8c26691023    4.7 GB    2 minutes ago     
llama2-uncensored:7b                     44040b922233    3.8 GB    53 minutes ago    
deepseek-r1:14b                          ea35dfe18182    9.0 GB    55 minutes ago    
huihui_ai/deepseek-r1-abliterated:14b    6b2209ffd758    9.0 GB    57 minutes ago 
</pre>
<p>Um eines dieser Modelle zu starten, gebt ihr ein:</p>
<div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb9-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ollama</span> run MODELLNAME</span></code></pre></div>
<p>Also zum Beispiel</p>
<div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb10-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ollama</span> run deepseek-r1:7b</span></code></pre></div>
<p>oder</p>
<div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb11-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ollama</span> run huihui_ai/deepseek-r1-abliterated:14b</span></code></pre></div>
<p>Der Promt startet, und ihr könnt eure Eingabe machen. Das interessante bei DeepSeek-R1 ist, dass ihr den Reasoning-Prozess verfolgen könnt. Zwischen den tags <code>&lt;think&gt;&lt;/think&gt;</code> könnt ihr mitlesen, wie das Modell “nachdenkt”.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.produnis.de/blog/posts/2025-01-30-ollama/ollama1.webp" class="img-fluid figure-img"></p>
<figcaption>DeepSeek-R1 denkt nach, und ja, ich habe mich im ersten Prompt vertippt…</figcaption>
</figure>
</div>
</section>
<section id="fazit" class="level2">
<h2 class="anchored" data-anchor-id="fazit">Fazit</h2>
<p>Ollama macht es mir super einfach, verschiedene Modelle zu installieren und zu nutzen. Und es ist echt interessant, dem “thinking” zuzuschauen.</p>
<p>Generell ist es sowieso immer besser, seine lokale “KI” zu befragen, statt den Datenkraken die Infos einzuwerfen.</p>
</section>
<section id="weblinks" class="level2">
<h2 class="anchored" data-anchor-id="weblinks">Weblinks</h2>
<ul>
<li><a href="https://https://ollama.com/" class="uri">https://https://ollama.com/</a></li>
<li><a href="https://huggingface.co/huihui-ai/DeepSeek-R1-Distill-Qwen-14B-abliterated-v2" class="uri">https://huggingface.co/huihui-ai/DeepSeek-R1-Distill-Qwen-14B-abliterated-v2</a></li>
<li><a href="https://workos.com/blog/how-to-run-deepseek-r1-locally" class="uri">https://workos.com/blog/how-to-run-deepseek-r1-locally</a></li>
<li><a href="https://blog.fefe.de/?ts=996bef34" class="uri">https://blog.fefe.de/?ts=996bef34</a> (fefe initial über DeepSeek)</li>
</ul>
            <br><center>
            <div class="matrixfoot" id="matrixfooter">
            <a href="https://matrix.to/#/#produnis-blog:tchncs.de">
            <img src="https://www.produnis.de/images/Matrix.webp" width="60">
            </a>
            Diskussion per Matrix unter <a href="https://matrix.to/#/#produnis-blog:tchncs.de">https://matrix.to/#/#produnis-blog:tchncs.de</a>
            </div>
            </center><br>&nbsp;
        


</section>

 ]]></description>
  <category>ollama</category>
  <category>deepseek</category>
  <category>ubuntuusers</category>
  <guid>https://www.produnis.de/blog/posts/2025-01-30-ollama/</guid>
  <pubDate>Wed, 29 Jan 2025 21:58:00 GMT</pubDate>
  <media:content url="https://www.produnis.de/blog/posts/2025-01-30-ollama/deepseek.webp" medium="image" type="image/webp"/>
</item>
<item>
  <title>I2P Darknet</title>
  <dc:creator>Joe Slam</dc:creator>
  <link>https://www.produnis.de/blog/posts/2025-01-15-i2p/</link>
  <description><![CDATA[ 





<p><img src="https://www.produnis.de/blog/posts/2025-01-15-i2p/i2pbanner.png" class="img-fluid"></p>
<p>Das <strong>I</strong>nvisible <strong>I</strong>nternet <strong>P</strong>roject (I2P) ist ein freies Softwareprojekt mit dem Ziel, ein anonymes bzw. pseudonymes und dezentrales Netzwerk zu schaffen.</p>
<p>Ähnlich wie TOR baut I2P ein Darknet auf, welches parallel zum normalen Internet existiert.</p>
<p>Die Kommunikation bei I2P ist an beiden Enden vollständig verschlüsselt. Jedes Datenpaket durchläuft dabei vier separate Verschlüsselungsschichten. Die verschlüsselten Daten werden über eine Vielzahl von I2P-Routern auf anderen Rechnern geleitet, bevor sie schließlich den Zielrechner erreichen. Dieses Prinzip der anonymen Weiterleitung führt dazu, dass sowohl die Datenrate als auch die Latenz im Vergleich zum normalen Internet reduziert sind. Dieser Geschwindigkeitsverlust ist jedoch der notwendige “Preis” für die deutlich erhöhte Anonymität.</p>
<section id="implementationen" class="level2">
<h2 class="anchored" data-anchor-id="implementationen">Implementationen</h2>
<p>Stand 2025 stehen zwei Implementationen von I2P zur Verfügung:</p>
<ol type="1">
<li><code>i2prouter</code> (Java suite, Standard) - benutzerfreundliche und interaktive Web-Benutzeroberfläche, welche viele Funktionen beinhaltet (z.B. E-Mail-Client, Torrent-Client, Webserver).</li>
<li><code>i2pd</code> (C++, Alternative) - benötigt kein Java und kommt mit weniger Systemressourcen aus, ist dafür aber auch “nur” ein nackter Router.</li>
</ol>
<section id="i2prouter" class="level3">
<h3 class="anchored" data-anchor-id="i2prouter"><code>i2prouter</code></h3>
<p>Die Standardimplementation benötigt ein Java-Runtime-Environmnent, genauer gesagt läuft sie nur mit <code>openjdk</code>, nicht aber mit <code>openjdk/jre</code></p>
<p>Unter Archlinux erfolgt die Installation per:</p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">yay</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-S</span> i2p-bin jdk-openjdk</span></code></pre></div>
<p>Anschließend kann noch sichergestellt werden, dass die korrekte Java-Version verwendet wird:</p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">archlinux-java</span> status</span>
<span id="cb2-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">archlinux-java</span> set JAVAVERSION</span></code></pre></div>
<p>Nach der Installation kann der Router per <code>systemd</code> gestartet werden.</p>
<div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb3-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> systemctl start i2prouter.service</span>
<span id="cb3-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> systemctl enable i2prouter.service</span></code></pre></div>
<p>Ist der Service gestartet, steht das Webinterface unter <a href="http://127.0.0.1:7657" class="uri">http://127.0.0.1:7657</a> bereit und führt euch durch die ersten Schritte. Ihr könnt die Standardeinstellungen so belassen und einfach immer auf “Weiter” klicken. Alle Einstellungen können später wieder geändert werden. Habt ihr euch durchgeklickt, begrüßt euch die Startseite eures I2P Routers.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.produnis.de/blog/posts/2025-01-15-i2p/i2p-router-01.webp" class="img-fluid figure-img"></p>
<figcaption>I2P Webinterface</figcaption>
</figure>
</div>
</section>
<section id="i2pd" class="level3">
<h3 class="anchored" data-anchor-id="i2pd"><code>i2pd</code></h3>
<p>Der I2P Daemon (i2pd) ist eine alternative Implementation, die ohne Java auskommt. Bei dieser Variante müssen alle Dienste (E-Mail, Torrent, Webserver) “von Hand” eingerichtet werden. Ich persönlich nutze diese Version auf Servern, um Transitknotenpunkte für das I2P-Netzwerk bereitzustellen.</p>
<p>Die Installation erfolgt unter Archlinux per</p>
<div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb4-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> pacman <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-S</span> i2pd</span></code></pre></div>
<p>und der Router kann ebenfalls per <code>systemd</code> gesteuert werden</p>
<div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb5-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> systemctl start i2pd.service</span>
<span id="cb5-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> systemctl enable i2pd.service</span></code></pre></div>
<p>Ist der Service gestartet, steht unter <a href="http://127.0.0.1:7070" class="uri">http://127.0.0.1:7070</a> eine Willkommensseite bereit. Ebenso ist ein Proxy für das Surfen im I2P-Darknet implementiert, der Anfragen über <a href="http://127.0.0.1:4444" class="uri">http://127.0.0.1:4444</a> entgegennimmt (siehe unten).</p>
</section>
</section>
<section id="i2p-webseiten-eepsites" class="level2">
<h2 class="anchored" data-anchor-id="i2p-webseiten-eepsites">i2p Webseiten (eepsites)</h2>
<p>Ähnlich wie bei TOR können im I2P-Netz <em>hidden services</em> eingerichtet werden. Webseiten heissen in I2P <em>eepsites</em> und haben die Topleveldomain <code>*.i2p</code>.</p>
<p>Um eine solche Seite ansurfen zu können, müssen 2 Aufgaben erfüllt sein:</p>
<ol type="1">
<li><p>Wir benötigen einen Browser, der den Proxydienst des I2P-Routers für Webanfragen benutzt. Bei beiden Implementationen (<code>i2prouter</code> und <code>i2pd</code>) lauscht dieser Proxy auf Port <code>http://127.0.0.1:4444</code>. Grundsätzlich empfiehlt es sich, für die Nutzung von I2P einen eigenen Browser zu benutzen. Zumindest solltet ihr ein eigenes Browserprofil für I2P verwenden. Hierbei ist die Firefox-Extension <a href="https://github.com/zero-peak/ZeroOmega">Zero Omega Switch</a> empfehlenswert. Ist diese installiert, kann ihr “Auto-Switch” so eingestellt werden, dass nur Anfragen an <code>*.i2p</code>-URLs an den Proxy weitergereicht werden. So können “normales” Web und I2P Darknet <em>nebeneinander</em> genutzt werden.</p>
<p>Hierfür lege ich mir in den Einstellungen der Extension ein Profil “i2p proxy” an, welches auf Port <code>4444</code> verweist… <img src="https://www.produnis.de/blog/posts/2025-01-15-i2p/i2p-omega1.webp" class="img-fluid" alt="Ein neues Profil “i2p proxy” verweist auf Port 4444"></p>
<p>… unter “Auto switch” wähle ich “Host wildcard” und trage das Pattern <code>*.i2p</code> ein. Dieses zeigt dann auf mein Profil “i2p proxy”.</p></li>
</ol>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.produnis.de/blog/posts/2025-01-15-i2p/i2p-omega2.webp" class="img-fluid figure-img"></p>
<figcaption>URLs mit der Endung <code>*.i2p</code> werden an den Proxy weitergeleitet</figcaption>
</figure>
</div>
<div class="callout callout-style-default callout-important callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Wichtig
</div>
</div>
<div class="callout-body-container callout-body">
<p>Damit der Auto-Switch funktioniert, sollte in der Adresszeile des Browsers nach dem <code>*.i2p</code> ein Slash verwendet werden, z.B. <a href="http://planet.i2p/" class="uri">http://planet.i2p/</a>.</p>
</div>
</div>
<p><br></p>
<ol start="2" type="1">
<li>Wir benötigen die “richtige” Adresse der Webseite. Das I2P-Netz ist dezentral organisiert. Das bedeutet, dass jede Installation ihr eigenes DNS-Adressbuch aufbauen muss. Die meisten <code>*.i2p</code>-Webseiten sind daher nach einer frischen Installation noch gar nicht erreichbar, weil der Router nicht weiss, welche “echte” Adresse sich hinter dem Namen verbirgt. Eine typische I2P-Adresse lautet</li>
</ol>
<blockquote class="blockquote">
<p><code>gOSToOvSkRewCcwl5mWXbnn1IElEBlGH92vAe0TI8C-Z4tC1DVMNdNlcnUTRcB7znjFTP0vQ42dIDs1dN2Co1kSJ~nXaef4QUS-Ou5kDogPLwJxI1Hj0djktSLKWJSL40FdQvWZ1rwQ7dnaRSyOm8lrgo~HbVlh682CM1JHmEGapQaYiF6zaP4uOpeTFlkk6wEYevQ3Pn4pctJD4XElVLrS2slEsbzim3O5FzFrIVYyskEbnpyMpyffwvsq0R~RF6bhDhQ15rAmJuju91WZ8iUlORQKipougCwBP9DxQ5zdXQWxxhSJ~h604dKhxncetl0skdErLHjwhSI2gl4o66juP9wsjaczBZo4RSil2uWMWApMgvan~9FSRtxriI5f6-X2fTopWa9KlUwMCBTiqYAy9bIdVVhS-xSdFhM~IGPEZ-rlIscdb3Z5Gh1osoO-~SglUcOpj7E-8XjjvsmLkUu9VBxscdD4p3aiyaHGSljkd3WPvlfaOBmqejqEgEWwqBQAEAAEAAA==</code></p>
</blockquote>
<p>Solche Adressen sind jedoch viel zu lang und unpraktisch. Daher wird ein Hashwert aus der Adresse generiert, über den die Seite einfacher aufgerufen werden kann – die sogenannte b32-Adresse. Im obigen Beispiel lautet die entsprechende b32-Hash-Adresse:</p>
<blockquote class="blockquote">
<p><code>http://nytzrhrjjfsutowojvxi7hphesskpqqr65wpistz6wa7cpajhp7a.b32.i2p/</code></p>
</blockquote>
<p>Dies ist schon eher handlebar und ähnelt den <code>*.onion</code>-Adressen des TOR-Netzes. Wenn ihr diese Adresse in euren Browser eingebt, könnt ihr die Seite direkt ansurfen. Schöner wäre natürlich, wenn die Seite über eine “menschenlesbare” Adresse erreichbar wäre, z.B. <a href="http://notbob.i2p/" class="uri">http://notbob.i2p/</a>. Um dies zu erreichen, muss ein lokaler DNS-Eintrag im Adressbuch des eigenen I2P-Routers erfolgen. Hierfür stehen im I2P-Netz so genannte “Helperlinks” zur Verfügung, die das Eintragen vereinfachen. Um die URL <code>notbob.i2p</code> mit der Adresse <code>nytzrhrjjfsutowojvxi7hphesskpqqr65wpistz6wa7cpajhp7a.b32.i2p</code> zu verknüpfen, könnt ihr einfach diesem Link folgen:</p>
<p><a href="http://notbob.i2p/?i2paddresshelper=nytzrhrjjfsutowojvxi7hphesskpqqr65wpistz6wa7cpajhp7a.b32.i2p">http://notbob.i2p/?i2paddresshelper=nytzrhrjjfsutowojvxi7hphesskpqqr65wpistz6wa7cpajhp7a.b32.i2p</a>.</p>
</section>
<section id="adressbuch" class="level2">
<h2 class="anchored" data-anchor-id="adressbuch">Adressbuch</h2>
<p>Die Adresse für <code>notbob.i2p</code> kann so im Adressbuch gespeichert werden.</p>
<p>(bitte nicht wundern, warum im Screenshot “produnis.i2p” steht. Ich recycle das Bild von weiter unten…)</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.produnis.de/blog/posts/2025-01-15-i2p/i2p-hidden4.webp" class="img-fluid figure-img"></p>
<figcaption>Helperlink ins Adressbuch speichern</figcaption>
</figure>
</div>
<p>Dabei besteht das Adressbuch aus 3 Teilen:</p>
<ol type="1">
<li><strong>Router Adressbuch</strong></li>
<li><strong>Lokales Adressbuch</strong></li>
<li><strong>Privates Adressbuch</strong></li>
</ol>
<p>Alle Bücher können über das Webinterface unter <a href="http://127.0.0.1:7657/dns" class="uri">http://127.0.0.1:7657/dns</a> eingesehen werden.</p>
<section id="router-adressbuch" class="level3">
<h3 class="anchored" data-anchor-id="router-adressbuch">Router Adressbuch</h3>
<p>Das Router-Adressbuch ist eine automatisch verwaltete Liste, die von eurem I2P-Router gepflegt wird. Hier solltet ihr nichts von Hand ändern. Es gibt Dienste im I2P-Netz, welche “fertige” Adressbucheinträge verteilen. Hat man solche Dienste aboniert, füllt sich das eigene Router Adressbuch mit Adressen und Links, die von den Diensten verteilt werden. Ihr könnt eure Abos unter dem Link <a href="http://127.0.0.1:7657/susidns/subscriptions" class="uri">http://127.0.0.1:7657/susidns/subscriptions</a> einsehen und erweitern. Folgende Einträge solltet ihr dort ergänzen, um die bekanntesten eepsites erreichen zu können:</p>
<div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb6-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">http://i2p-projekt.i2p/hosts.txt</span></span>
<span id="cb6-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">http://identiguy.i2p/hosts.txt</span></span>
<span id="cb6-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">http://notbob.i2p/hosts.txt</span></span>
<span id="cb6-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">http://reg.i2p/hosts.txt</span></span>
<span id="cb6-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">http://skank.i2p/hosts.txt</span></span>
<span id="cb6-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">http://stats.i2p/cgi-bin/newhosts.txt</span></span></code></pre></div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.produnis.de/blog/posts/2025-01-15-i2p/i2p-routerabo1.webp" class="img-fluid figure-img"></p>
<figcaption>eingetragene Abo-Dienste</figcaption>
</figure>
</div>
<p>Wenn ihr auf “Speichern” geklickt habt, könnt ihr sehen, wie sich euer Router Adressbuch nach und nach mit Einträgen füllt. Jetzt solltet ihr z.B. diese eepsites erreichen können:</p>
<ul>
<li><a href="http://planet.i2p/" class="uri">http://planet.i2p/</a></li>
<li><a href="http://wir-in-nepal.i2p/" class="uri">http://wir-in-nepal.i2p/</a></li>
</ul>
</section>
<section id="lokales-adressbuch" class="level3">
<h3 class="anchored" data-anchor-id="lokales-adressbuch">lokales Adressbuch</h3>
<p>Solltet ihr - woher auch immer - eine neue b32-Adresse erhalten haben, könnt ihr mittels Helper-Link (oder auch “von Hand”) einen neuen Eintrag in eurem lokalen Adressbuch erzeugen. Die Einträge im lokalen Adressbuch stellen euer persönliches Verzeichnis dar und werden nicht an andere I2P-Router weitergegeben.</p>
</section>
<section id="privates-adressbuch" class="level3">
<h3 class="anchored" data-anchor-id="privates-adressbuch">privates Adressbuch</h3>
<p>Das private Adressbuch speichert sensiblere Adressen, die ihr getrennt von eurem lokalen Adressbuch speichern wollt. Es wird genutzt, um hochsensible Ziele oder Dienste zu speichern, die ihr nicht versehentlich teilen möchtet. Einträge im privaten Adressbuch werden weder verteilt noch sind sie von anderen I2P-Komponenten zugänglich.</p>
</section>
</section>
<section id="e-mail" class="level2">
<h2 class="anchored" data-anchor-id="e-mail">E-Mail</h2>
<p>Unter dem Link <a href="http://127.0.0.1:7657/webmail" class="uri">http://127.0.0.1:7657/webmail</a> ist der Mail-Client SusiMail erreichbar. In I2P lauten die Standardmailadressen <code>USERNAME@mail.i2p</code>. Ihr könnt euch beliebig viele Mailadressen kostenlos anlegen. Klickt dafür auf “Konto anlegen” oder folgt dem Link <a href="http://hq.postman.i2p/?page_id=16" class="uri">http://hq.postman.i2p/?page_id=16</a>. Die Adresse von <code>postman.i2p</code> ist bereits im Router-Adressbuch gespeichert, sofern ihr die oben genannten Dienst abonniert habt.</p>
</section>
<section id="torrent" class="level2">
<h2 class="anchored" data-anchor-id="torrent">Torrent</h2>
<p>Mit I2Psnark steht euch unter <a href="http://127.0.0.1:7657/torrents" class="uri">http://127.0.0.1:7657/torrents</a> ein Torrent-Client zur Verfügung. Das Datenverzeichnis liegt standardmäßig unter <code>/opt/i2p/.i2p/i2psnark/</code>. Wenn ihr in dieses Verzeichnis eine Torrentdatei ablegt, wird sie automatisch dem Client hinzugefügt. Natürlich geht das auch über das Webinterface.</p>
<p>Der bekannteste Tracker ist unter <a href="https://tracker2.postman.i2p/" class="uri">https://tracker2.postman.i2p/</a> erreichbar. Die Seite steht dauerhaft unter “heavy use”, weshalb es sein kann, dass ihr zwei bis drei Anläufe nehmen müsst, um draufzukommen. Dies gilt generell für alle eepsites: wenn sie mal nicht erreichbar ist, wartet einfach 60 Sekunden und versucht es erneut. Dabei wird ein neuer Verbindungstunnel aufgebaut, und die Seiten sind dann meist erreichbar.</p>
<p>Ich habe bei mir noch die Bandbreit für die Torrents angepasst. Klickt hierfür auf der Torrentseite unten auf “Konfiguration”. Meine Bandbreite für Uploads habe ich auf <code>2048</code>, und für Downloads auf <code>4096 Kbps</code> gestellt.</p>
<p>Das I2P-Netz ist eher langsam, so dass es eine Zeit dauert, bis größere Torrents vollständig sind, aber: steter Tropfen höhlt den Stein.</p>
<section id="eigenen-torrent-erstellen" class="level3">
<h3 class="anchored" data-anchor-id="eigenen-torrent-erstellen">eigenen Torrent erstellen</h3>
<p>Ich habe es nicht geschafft, einen eigenen Torrent über das Webinterface zu erzeugen. Daher habe ich auf <code>mktorrent</code> zurückgegriffen. So konnte ich eine Torrentdatei für mein <a href="https://github.com/produnis/angewandte_uebungen_in_R">R-Buch</a> anlegen.</p>
<p>Der allgemeine Aufruf lautet:</p>
<div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb7-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">mktorrent</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-a</span> http://tracker2.postman.i2p/announce.php <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> MeineDaten.torrent MeineDaten</span></code></pre></div>
<p>In meinem Fall also:</p>
<div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb8-1"></span>
<span id="cb8-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">mktorrent</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-a</span> http://tracker2.postman.i2p/announce.php <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> grSchlarmann2024--Angewandte-Uebungen-in-R.torrent grSchlarmann2024--Angewandte-Uebungen-in-R.pdf</span></code></pre></div>
<p>Die Verwendung des Trackers ist übrigens nicht notwendig. Die Torrents verteilen sich auch ohne Tracker per DTH.</p>
<p>Ich habe beide Dateien in mein i2psnark-Verzeichnis verschoben und die Rechte wie folgt angepasst:</p>
<div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb9-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># kopieren</span></span>
<span id="cb9-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> cp grSchlarmann2024<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">*</span> /opt/i2p/.i2p/i2psnark/</span>
<span id="cb9-3"></span>
<span id="cb9-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Rechte anpassen</span></span>
<span id="cb9-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> chown i2p:i2p <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-R</span> /opt/i2p/.i2p/i2psnark/<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">*</span></span></code></pre></div>
<p>Im Webinterface sehe ich nun, dass der Torrent erfolgreich hinzugefügt wurde.</p>
<p><img src="https://www.produnis.de/blog/posts/2025-01-15-i2p/i2p-01.webp" class="img-fluid" alt="Torrent starten"> Sobald ich auf den Startknopf (siehe roter Pfeil) klicke, beginnt die Verteilung an alle Interessierten. Das Webinterface meldet ebenfalls, dass der Torrent gestartet wurde.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.produnis.de/blog/posts/2025-01-15-i2p/i2p-02.webp" class="img-fluid figure-img"></p>
<figcaption>Torrent ist gestartet</figcaption>
</figure>
</div>
<p>Über das blaue Ausrufezeichen kann ich mir den Torrent genauer anschauen. Hier finde ich auch den Magnet-Link, den ich verteilen kann. Jeder, der diesen Link seinem I2P-Torrent hinzufügt, kann die Datei herunterladen.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.produnis.de/blog/posts/2025-01-15-i2p/i2p-03.webp" class="img-fluid figure-img"></p>
<figcaption>Torrentinformationen</figcaption>
</figure>
</div>
<p>In meinem Fall lautet der Link <a href="magnet:?xt=urn:btih:2937cd3471893db9a23ba8ce9cc4ac78efbde4d5&amp;tr=http://tracker2.postman.i2p/announce.php">magnet:?xt=urn:btih:2937cd3471893db9a23ba8ce9cc4ac78efbde4d5&amp;tr=http://tracker2.postman.i2p/announce.php</a>, fügt ihn gerne zu Testzwecken eurem Client hinzu :-)</p>
<p>Alternativ könnt ihr euch auch das Video <em>I2P - Protocol of Invisible Internet. How the best anonymity network works</em> über <code>magnet:?xt=urn:btih:45914a6116c37b9b3eb526e28cedc1d3af64ac1d</code> herunterladen (das Video gibt es aber auch bei <a href="https://www.youtube.com/watch?v=95hSAMEwrlM">Youtube</a>).</p>
</section>
</section>
<section id="webserver" class="level2">
<h2 class="anchored" data-anchor-id="webserver">Webserver</h2>
<p>Ebenfalls enthalten ist der Webserver Jetty, mit welchem ihr eure eigene eepsite bereitstellen könnt. Am besten eigenen sich hierfür statische Seiten, die z.B. mittels <a href="https://gohugo.io">HUGO</a> gebaut wurden.</p>
<p>Legt zunächst eure HTML-Dateien samt Zubehör in den Ordner <code>/opt/i2p/.i2p/eepsite/docroot/</code>.</p>
<p>Im Webinterface findet ihr den Eintrag “Versteckte Dienst verwalten” unter <a href="http://127.0.0.1:7657/i2ptunnelmgr" class="uri">http://127.0.0.1:7657/i2ptunnelmgr</a>. Dort seht ihr unter “I2P Versteckte Services” den Eintrag “I2P webserver”. Klickt darauf, um die grundlegenen Informationen eurer eepsite anzugeben. Bei mir sieht das so aus:</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.produnis.de/blog/posts/2025-01-15-i2p/i2p-hidden3.webp" class="img-fluid figure-img"></p>
<figcaption>Meine eepsite</figcaption>
</figure>
</div>
<p>Jetzt muss der Webserver an zwei Stellen aktiviert werden. Geht zunächst nach <a href="http://127.0.0.1:7657/config" class="uri">http://127.0.0.1:7657/config</a> und wählt dort den Reiter “Teilnehmer”.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.produnis.de/blog/posts/2025-01-15-i2p/i2p-hidden2.webp" class="img-fluid figure-img"></p>
<figcaption>Reiter “Teilnehmer” (links)</figcaption>
</figure>
</div>
<p>Hier muss der Startknopf gedrückt werden. Optional könnt ihr den Haken setzen, so dass der Server beim Neustart automatisch mitgestartet wird.</p>
<p>Nun läuft der Webserver Jetty, aber der I2P-Tunnel zum Webserver ist noch nicht aktiviert. Klickt hierfür wieder auf <a href="http://127.0.0.1:7657/i2ptunnelmgr" class="uri">http://127.0.0.1:7657/i2ptunnelmgr</a> und dort auf den Start-Knopf.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.produnis.de/blog/posts/2025-01-15-i2p/i2p-hidden1.webp" class="img-fluid figure-img"></p>
<figcaption>Tunnel per Startknopf starten</figcaption>
</figure>
</div>
<p>Der Status sollte nun von rot auf grün welchseln.</p>
<p><img src="https://www.produnis.de/blog/posts/2025-01-15-i2p/i2p-hidden5.webp" class="img-fluid" alt="Helper-Adresse kopieren"> Ebenfalls wurde ein Helperlink erzeugt, der nun fleissig weiterverteilt werden kann. Bei mir lautet der klassische I2P-DNS-Dreisatz: <a href="http://produnis.i2p/" class="uri">http://produnis.i2p/</a> (<a href="http://produnisdew2vlsutbkvrlpqfckucifanpctwksofolelnudvrtq.b32.i2p/">b32</a>) (<a href="http://produnis.i2p/?i2paddresshelper=AEw1Vvl9Oc3RJpPjgbWI75DJfN7J9-VnHPBi15AvOb8wFtNY5Zs~nvreuqwDmlqWgX-Re7OCQzCmejUpssPLjvoKfO3Y2L4NU-QYDbymHrfZdpB94JsvrqKtgVSPE9RmkTAjZ80E3WiOLP-wpApZgOQgIIj-9p9KgQ~TsI0bEnRz7ReHz6ABR2WDhvhTJMU~PPxlCRq0OrhMQ-t59WJ9~0G12d3FjhAzNpiGvS79dG3YM5GpC8lveDkYpo3VdGN4D4gn6MBDZU5eXXbfEmyYa1NsAbLgwa8ODb9OE2aKrE91jl~1PH1uSui-umK4Qr7wqzk6uhe2qkc8EoQThYN3RPWD5Ebq78krXZGkxkrhv1AlURpZ~L5fDovAlDetSb~N9YPkRurvyStdkaTGSuG~UCVRGln8vl8Oi8CUN61Jv809V4Vq6u~JK12RpMZK4b9QJVEaWfy-Xw6LwJQ3rUm~zU46CHR2ZnaNupVjwoYUSbGBzKs7-CTVdoSjAdEMKGGsBQAEAAcAAA==">Helper</a>)</p>
<p>Speichert mich gerne in euer lokales Adressbuch :-)</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.produnis.de/blog/posts/2025-01-15-i2p/i2p-hidden4.webp" class="img-fluid figure-img"></p>
<figcaption>Helperlink ins Adressbuch speichern</figcaption>
</figure>
</div>
<p>Ich wünsche euch viel Spaß beim Ausprobieren und Herumexperimentieren. Eine echt coole Seite ist übrigens <a href="http://i2puzzle.i2p/" class="uri">http://i2puzzle.i2p/</a> (<a href="http://i2puzzle.i2p/?i2paddresshelper=gWOTGa1fbqfp~w32mDrbhLXmPohoewjm2QCmkJvR-fisqMq2EFVgTVzYTapbudic5VFtQmeYaLFSMs3RS5fSfZDo8OAOgY7jzWLnG9Ntch1st4~eLB7bQNrC80g9Zzn6~Tw03~6L5woL0Gmf1TsDrZ3Hj2SIqqzIOIhrf3oqi4rSWgNO6V29cIv5NYPw2jDnid6ilC54g3ganxp07~5oFS7veftZW4WOy0f6-1RdNV~a2PGgwWMXBlCKdcDQUxYxL-jRlvovNz7HxEMG-y5mcycVjf8-L3tdBsyPkhka6iEev2z8AFTTbVaBcbJFHtiuX-qRzUY52JC-cBtuFYttY5sO~C653MiCZm2H5FRsPVewVKWD0fgZkHkdi9zPunCSmw78LrncyIJmbYfkVGw9V7BUpYPR-BmQeR2L3M-6cJLZgCAxudzIgmZth-RUbD1XsFSlg9H4GZB5HYvcz7pwknWMu-kVFmMs8XZtXu~HwZK6j1UTTP40YtCdky0b22~MBQAEAAcAAA==">helper</a>), falls ihr gerne Rätsel löst…</p>
</section>
<section id="weblinks" class="level2">
<h2 class="anchored" data-anchor-id="weblinks">Weblinks</h2>
<ul>
<li><a href="https://de.wikipedia.org/wiki/I2P" class="uri">https://de.wikipedia.org/wiki/I2P</a></li>
<li><a href="https://geti2p.net/de/" class="uri">https://geti2p.net/de/</a></li>
<li><a href="https://i2pd.website/" class="uri">https://i2pd.website/</a></li>
<li><a href="https://www.youtube.com/watch?v=95hSAMEwrlM" class="uri">https://www.youtube.com/watch?v=95hSAMEwrlM</a></li>
<li><a href="https://github.com/zero-peak/ZeroOmega" class="uri">https://github.com/zero-peak/ZeroOmega</a></li>
<li><a href="https://wiki.archlinux.org/title/I2P" class="uri">https://wiki.archlinux.org/title/I2P</a></li>
</ul>
            <br><center>
            <div class="matrixfoot" id="matrixfooter">
            <a href="https://matrix.to/#/#produnis-blog:tchncs.de">
            <img src="https://www.produnis.de/images/Matrix.webp" width="60">
            </a>
            Diskussion per Matrix unter <a href="https://matrix.to/#/#produnis-blog:tchncs.de">https://matrix.to/#/#produnis-blog:tchncs.de</a>
            </div>
            </center><br>&nbsp;
        


</section>

 ]]></description>
  <category>i2p</category>
  <category>ubuntuusers</category>
  <guid>https://www.produnis.de/blog/posts/2025-01-15-i2p/</guid>
  <pubDate>Wed, 15 Jan 2025 19:40:00 GMT</pubDate>
  <media:content url="https://www.produnis.de/blog/posts/2025-01-15-i2p/i2plogo.png" medium="image" type="image/png" height="144" width="144"/>
</item>
<item>
  <title>Eine Typst-Extension für Quarto erstellen</title>
  <dc:creator>Joe Slam</dc:creator>
  <link>https://www.produnis.de/blog/posts/2024-11-16-quarto-typst-extension/</link>
  <description><![CDATA[ 





<p><a href="https://typst.app/">Typst</a> ist ein relativ neues open-source Textsatzsystem, das als Alternative zu LaTeX entwickelt wurde. Es zeichnet sich durch eine einfachere Syntax und eine intuitivere Bedienung aus, während es dennoch die leistungsstarken Formatierungs- und Gestaltungsmöglichkeiten bietet, die für wissenschaftliche und technische Dokumente erforderlich sind.</p>
<p>Seit der Version 1.4 (Januar 2024) ist Typst in <a href="https://quarto.org">Quarto</a> enthalten und kann daher direkt verwendet werden um PDF-Dokumente zu erzeugen, siehe <a href="https://quarto.org/docs/output-formats/typst.html" class="uri">https://quarto.org/docs/output-formats/typst.html</a>.</p>
<section id="vorteile-von-typst-gegenüber-latex" class="level2">
<h2 class="anchored" data-anchor-id="vorteile-von-typst-gegenüber-latex">Vorteile von Typst gegenüber LaTeX</h2>
<ul>
<li>Es ist unglaublich schnell! Typst ist in Rust geschrieben und verwendet inkrementelle Kompilierung, was schnellere Kompilierungszeiten ermöglicht. Selbst bei einfachen einseitigen Dokumenten ist es spürbar schneller als LaTeX.</li>
<li>Es ist direkt in Quarto enthalten und muss nicht zusätzlich installiert werden.</li>
<li>Die Syntax ist (ein wenig :-) ) einfacher als bei LaTeX.</li>
<li>Die Fehlermeldungen sind aussagekräftiger als bei LaTeX.</li>
</ul>
</section>
<section id="nachteile" class="level2">
<h2 class="anchored" data-anchor-id="nachteile">Nachteile</h2>
<ul>
<li>LaTeX kann viel mehr als Typst.</li>
<li>Typst ist noch relativ neu, es kann noch nicht <em>alles</em>. Es hat nichtmals einen Wikipediaeintrag (Stand 11/2024).</li>
<li>Falls ihr euch von “KI” inspirieren lassen wollt: ChatGTP und Co.&nbsp;können Typst quasi gar nicht und erzeugen großen Müll-Code.</li>
</ul>
</section>
<section id="pdf-dokumente" class="level2">
<h2 class="anchored" data-anchor-id="pdf-dokumente">PDF-Dokumente</h2>
<p>Seit Jahrzehnten (ja, ich bin alt) verwende ich LaTeX. Mittlerweile erzeuge ich alle meine Dokument mit Quarto, aber immerhin habe ich meine <em>schönsten</em> LaTeX Vorlagen in Quarto-Extensions ausgelagert, so dass ich sie “unter der Haube” immer noch verwende (siehe z.B. <a href="../2022-09-12-quarto-briefvorlage/">diesen Blogpost</a>). Das funktioniert sehr gut, und eigentlich bin ich auch zufrieden damit.</p>
<p>Dennoch habe ich einfach mal aus Spaß Typst ausprobiert, und vor allem die Geschwindigkeit des rendering hat mich sehr begeistert. Meine LaTeX Dokumente benötigen mindestens 2 (manchmal sogar 3) LaTeX-Läufe, die für sich schon relativ lange brauchen, um durchzulaufen. Typst hingegen ist nach einem Lauf fertig, und dieser Lauf ist einfach unglaublich schnell.</p>
<p>Also habe ich auf den Bahnfahrten angefangen, meine LaTeX-Extensions um Typst zu erweitern.</p>
</section>
<section id="eine-quarto-extension-erstellen" class="level2">
<h2 class="anchored" data-anchor-id="eine-quarto-extension-erstellen">Eine Quarto Extension erstellen</h2>
<p>Um eine neue Extension zu erstellen folge ich grob der <a href="https://quarto.org/docs/output-formats/typst-custom.html">Anleitung auf der Quarto Webseite</a>.</p>
<p>Für meine Extensions habe ich ein eigenes Verzeichnis. Per Terminal wechsel ich in dieses Verzeichnis und starte dort ein neues Extensionprojekt mit dem Befehl</p>
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>Terminal</strong></pre>
</div>
<div class="sourceCode" id="cb1" data-filename="Terminal" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> quarto create extension format</span></code></pre></div>
</div>
<p>Nun wähle ich <code>typst</code> aus der Auswahlliste und gebe erneut den Namen der Extension (<code>foobar</code>) ein. Anschließend kann der Ordner z.B. mit <code>vscodium</code> geöffnet werden.</p>
<p>Ich bearbeite die Dateien nicht in RStudio, da dort kein Syntax Highlighting für Typst angeboten wird. Ich nutze <a href="https://github.com/posit-dev/positron">Positron</a>, aber grundsätzlich geht es natürlich mit jedem Texteditor.</p>
<p>In meinem Ordner liegt nun ein neues Verzeichnis <code>foobar</code>, und in diesem sind die folgenden Dateien und Verzeichnisse zu finden:</p>
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>Dateistruktur im Ordner foobar</strong></pre>
</div>
<div class="sourceCode" id="cb2" data-filename="Dateistruktur im Ordner foobar" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">template.qmd</span></span>
<span id="cb2-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">README.md</span></span>
<span id="cb2-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">_extensions/</span></span>
<span id="cb2-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">_extensions/foobar/</span></span>
<span id="cb2-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">_extensions/foobar/_extension.yml</span></span>
<span id="cb2-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">_extensions/foobar/typst-show.typ</span></span>
<span id="cb2-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">_extensions/foobar/typst-template.typ</span></span></code></pre></div>
</div>
<p>Die Dateien sind bereits mit Standardinhalt befüllt, so dass die die Datei <code>template.qmd</code> direkt gerendert werden kann. Probiert es mal direkt aus!</p>
<p>Schaut euch die generierten Dateien an:</p>
<ul>
<li><code>template.qmd</code> - Das Dokument, welches gerendert werden soll.</li>
<li><code>README.md</code> - Eine README-Datei mit allen Infos zur Extension.</li>
<li><code>_extensions/</code> - Hier liegen alle Extensions, auf die <code>template.qmd</code> zugreifen kann.</li>
<li><code>_extensions/foobar/</code> - Hier liegt unsere Extension.</li>
<li><code>_extensions/foobar/_extension.yml</code> - Hier geben wir die Metadaten unserer Extension (Name, Autor, Beschreibung, etc.) an, sowie die bereitsgestellten Formate nebst Standardparameter</li>
<li><code>_extensions/foobar/typst-show.typ</code> - Diese Datei ruft unser eigentliches Template auf. Hier können zudem Pandoc-Metadaten an Funktionsparameter gemappt werden.</li>
<li><code>_extensions/foobar/typst-template.typ</code> - Unsere eigentliche Templatedatei.</li>
</ul>
<p>Für mich als Autodidakt war es herausfordernd, die Typst-Syntax zu lernen. Eine sehr wichtige Nachschlageseite hierfür ist <a href="https://typst.app/docs/" class="uri">https://typst.app/docs/</a>. Die Standardinhalte von <code>typst-show.typ</code> und <code>typst-template.typ</code> haben mich zunächst stark verwirrt, so dass ich in diesem Blogbeispiel mit leeren <code>.typ</code>-Dateien anfangen möchte.</p>
<section id="typst-show.typ" class="level3">
<h3 class="anchored" data-anchor-id="typst-show.typ"><code>typst-show.typ</code></h3>
<p>Die Datei <code>typst-show.typ</code> ruft unser eigentliches Template auf. Ich lösche den Standardinhalt und ersetze ihn mit dieser einzigen Funktion.</p>
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>typst-show.typ</strong></pre>
</div>
<div class="sourceCode" id="cb3" data-filename="typst-show.typ" style="background: #f1f3f5;"><pre class="sourceCode latex code-with-copy"><code class="sourceCode latex"><span id="cb3-1">#show: foobar.with(</span>
<span id="cb3-2"></span>
<span id="cb3-3">)</span></code></pre></div>
</div>
<p>Innerhalb dieser Funktion können wir (später) YAML-Parameter abgreifen. Dies funktioniert allerdings auch in der Datei <code>typst-template.typ</code>, so dass ich es hier zunächst auslasse.</p>
</section>
<section id="typst-template.typ" class="level3">
<h3 class="anchored" data-anchor-id="typst-template.typ"><code>typst-template.typ</code></h3>
<p>In der Datei <code>typst-template.typ</code> lebt unser eigentliches Template. Auch hier lösche ich den Standardinhalt und ersetze ihn durch</p>
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>typst-template.typ</strong></pre>
</div>
<div class="sourceCode" id="cb4" data-filename="typst-template.typ" style="background: #f1f3f5;"><pre class="sourceCode rust code-with-copy"><code class="sourceCode rust"><span id="cb4-1">#let foobar(</span>
<span id="cb4-2">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Welche Werte erwartet mein Template?</span></span>
<span id="cb4-3">  body</span>
<span id="cb4-4">) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb4-5">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Hier beginnt die Ausgabe</span></span>
<span id="cb4-6">  body</span>
<span id="cb4-7"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span></code></pre></div>
</div>
<p>Die Datei besteht aus 2 Teilen, <code>#let foobar()</code> definiert unsere Templatefunktion (die, die von <code>typst-show.typ</code> aufgerufen wird) und legt fest, welche Parameter diese Funktion erwartet. Standardmäßig steht hier nur <code>body</code>, womit der Inhalt unserer <code>template.qmd</code> gemeint ist.</p>
<p>Im zweiten Teil, welcher mit <code>={ ... }</code> eingeleitet wird, erfolgt das eigentliche Styling der Ausgabe. Auch hier steht derzeit nur <code>body</code>, was bedeutet, dass der Inhalt auf einer “blanken” Seite ausgegeben wird. Klickt mal jetzt auf “rendern”.</p>
</section>
<section id="typst-befehle-mit-und-ohne" class="level3">
<h3 class="anchored" data-anchor-id="typst-befehle-mit-und-ohne">Typst-Befehle mit und ohne <code>#</code></h3>
<p>Was mich am Anfang am meisten verwirrt hat ist, dass Typst-Befehle und -Variablen manchmal ein <code>#</code> vorangestellt benötigen, und manchmal nicht. So wie ich es verstanden habe</p>
<ul>
<li>wird bei jedem Befehl und jeder Variable ein <code>#</code> benötigt.</li>
<li>innerhalb von Funktions<strong>definitionen</strong> (z.B. der zweite Teil unserer <code>foobar</code> Funktion) dürfen keine <code>#</code> verwendet werden. Alles, was in <em>runden</em> Klammern steht, benötigt kein <code>#</code>.</li>
<li>innerhalb von Funktions<strong>aufrufen</strong> müssen wieder <code>#</code> gesetzt werden. Alles, was in <em>eckigen</em> Klammern steht, benötigt ein <code>#</code>.</li>
</ul>
</section>
<section id="yaml-parameter-direkt-auslesen" class="level3">
<h3 class="anchored" data-anchor-id="yaml-parameter-direkt-auslesen">YAML-Parameter direkt auslesen</h3>
<p>Parameter aus dem YAML-Header können wie gewohnt über Pandoc gemappt werden. In unserer Extension wollen wir zunächst den <code>title</code>-Parameter auslesen und ausgeben.</p>
<p>Wir können dies einerseits direkt in der <code>typst-template.typ</code> vornehmen</p>
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>typst-template.typ</strong></pre>
</div>
<div class="sourceCode" id="cb5" data-filename="typst-template.typ" style="background: #f1f3f5;"><pre class="sourceCode rust code-with-copy"><code class="sourceCode rust"><span id="cb5-1">#let foobar(</span>
<span id="cb5-2">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Welche Werte erwartet mein Template?</span></span>
<span id="cb5-3">  body</span>
<span id="cb5-4">) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb5-5">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Hier beginnt die Ausgabe</span></span>
<span id="cb5-6">  </span>
<span id="cb5-7">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// title anzeigen</span></span>
<span id="cb5-8">  text(36pt)[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>title<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>]</span>
<span id="cb5-9">  </span>
<span id="cb5-10">  body</span>
<span id="cb5-11"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span></code></pre></div>
</div>
<p>Wenn ihr jetzt rendert, seht ihr den großen Titel am Dokumentanfang.</p>
</section>
<section id="yaml-parameter-über-typst-show.typ-anmelden" class="level3">
<h3 class="anchored" data-anchor-id="yaml-parameter-über-typst-show.typ-anmelden">YAML-Parameter über <code>typst-show.typ</code> anmelden</h3>
<p>Ein anderer Weg, um den Parameter <code>title</code> aus dem YAML-Header zu lesen, erfolgt in 2 Schritten.</p>
<ol type="1">
<li>In der Datei <code>typst-show.typ</code> lesen wir den Parameter aus und weisen ihn der Variable <code>meintitel</code> zu:</li>
</ol>
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>typst-show.typ</strong></pre>
</div>
<div class="sourceCode" id="cb6" data-filename="typst-show.typ" style="background: #f1f3f5;"><pre class="sourceCode latex code-with-copy"><code class="sourceCode latex"><span id="cb6-1">#show: foobar.with(</span>
<span id="cb6-2">  meintitel: "<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">$title$</span>",</span>
<span id="cb6-3">)</span></code></pre></div>
</div>
<p>Beachtet, dass <code>$title$</code> in Anführungszeichen gewickelt werden muss. Wir können hier noch sicherstellen, dass die Zuweisung nur dann erfolgt, wenn der Parameter auch wirklich im YAML angegeben ist:</p>
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>typst-show.typ</strong></pre>
</div>
<div class="sourceCode" id="cb7" data-filename="typst-show.typ" style="background: #f1f3f5;"><pre class="sourceCode latex code-with-copy"><code class="sourceCode latex"><span id="cb7-1">#show: foobar.with(</span>
<span id="cb7-2">  <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">$if(title)$</span></span>
<span id="cb7-3">    meintitel: "<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">$title$</span>",</span>
<span id="cb7-4">  <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">$endif$</span></span>
<span id="cb7-5">)</span></code></pre></div>
</div>
<ol start="2" type="1">
<li>In der Datei <code>typst-template.typ</code> geben wir an, dass die Variable <code>meintitel</code> zuvor ausgelesen wurde. Somit steht uns im unteren Teil des Templates die Variable <code>#meintitel</code> zur Verfügung, und der Befehl zur Titelausgabe ändert sich entsprechend in <code>text(36pt)[#meintitel]</code>.</li>
</ol>
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>typst-template.typ</strong></pre>
</div>
<div class="sourceCode" id="cb8" data-filename="typst-template.typ" style="background: #f1f3f5;"><pre class="sourceCode rust code-with-copy"><code class="sourceCode rust"><span id="cb8-1">#let foobar(</span>
<span id="cb8-2">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Welche Werte erwartet mein Template?</span></span>
<span id="cb8-3">  meintitel<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> none<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb8-4">  body</span>
<span id="cb8-5">) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb8-6">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Hier beginnt die Ausgabe</span></span>
<span id="cb8-7">  </span>
<span id="cb8-8">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// title anzeigen</span></span>
<span id="cb8-9">  text(36pt)[#meintitel]</span>
<span id="cb8-10">  </span>
<span id="cb8-11">  body</span>
<span id="cb8-12"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span></code></pre></div>
</div>
<p>Im oberen Teil haben wir <code>meintitel: none,</code> angegeben, was bedeutet, dass die Variable leer bleibt, sofern sie nicht im YAML angegeben ist. Natürlich können wir hier auch Standardwerte hinterlegen, z.B:</p>
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>typst-template.typ</strong></pre>
</div>
<div class="sourceCode" id="cb9" data-filename="typst-template.typ" style="background: #f1f3f5;"><pre class="sourceCode rust code-with-copy"><code class="sourceCode rust"><span id="cb9-1">#let foobar(</span>
<span id="cb9-2">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Welche Werte erwartet mein Template?</span></span>
<span id="cb9-3">  meintitel<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Du hast den Titel vergessen"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb9-4">  body</span>
<span id="cb9-5">) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb9-6">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Hier beginnt die Ausgabe</span></span>
<span id="cb9-7">  </span>
<span id="cb9-8">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// title anzeigen</span></span>
<span id="cb9-9">  text(36pt)[#meintitel]</span>
<span id="cb9-10">  </span>
<span id="cb9-11">  body</span>
<span id="cb9-12"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span></code></pre></div>
</div>
<p>Wenn Sie nun in <code>template.qmd</code> den YAML-Parameter <code>title</code> entfernen, greift typst auf den Standardwert <code>"Du hast den Titel vergessen"</code> zurück.</p>
</section>
<section id="was-ist-nun-besser" class="level3">
<h3 class="anchored" data-anchor-id="was-ist-nun-besser">Was ist nun besser?</h3>
<p>Ich habe noch nicht genau verstanden, wie die Parameter “am besten” abgegriffen werden. Es funktioniert jedenfalls alles wunderbar, wenn <code>typst-show.typ</code> quasi leer bleibt, und alle Parameter direkt in der <code>typst-template.typ</code> verarbeitet werden. Naja, ihr kennt nun beide Vorgehensweisen und könnt selbst auswählen…. :-)</p>
</section>
<section id="bilddateien-bereitstellen-sonderzeichen-escapen" class="level3">
<h3 class="anchored" data-anchor-id="bilddateien-bereitstellen-sonderzeichen-escapen">Bilddateien bereitstellen (Sonderzeichen escapen)</h3>
<p>Manche meiner Extensions bringen Logo-Dateien mit (z.B. meine Briefvorlage an der Hochschule). Die Logos liegen ebenfalls im <code>_extensions</code>-Ordner und werden über die <code>_extension.yml</code> angegeben:</p>
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>_extension.yml</strong></pre>
</div>
<div class="sourceCode" id="cb10" data-filename="_extension.yml" style="background: #f1f3f5;"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb10-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">title</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> Foobar</span></span>
<span id="cb10-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">author</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> Joe Slam</span></span>
<span id="cb10-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">version</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0.0</span></span>
<span id="cb10-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">quarto-required</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"&gt;=1.5.0"</span></span>
<span id="cb10-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">contributes</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb10-6"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">formats</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb10-7"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">typst</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb10-8"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">logo</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> MeinLogo.png</span></span>
<span id="cb10-9"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">template-partials</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb10-10"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> typst-template.typ</span></span>
<span id="cb10-11"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> typst-show.typ</span></span></code></pre></div>
</div>
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>Dateistruktur im Ordner foobar</strong></pre>
</div>
<div class="sourceCode" id="cb11" data-filename="Dateistruktur im Ordner foobar" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb11-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">template.qmd</span></span>
<span id="cb11-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">README.md</span></span>
<span id="cb11-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">_extensions/</span></span>
<span id="cb11-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">_extensions/foobar/</span></span>
<span id="cb11-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">_extensions/foobar/_extension.yml</span></span>
<span id="cb11-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">_extensions/foobar/typst-show.typ</span></span>
<span id="cb11-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">_extensions/foobar/typst-template.typ</span></span>
<span id="cb11-8"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">_extensions/foobar/MeinLogo.png</span></span></code></pre></div>
</div>
<p>Das Problem besteht darin, dass der relative Pfad zur Logodatei ein Sonderzeichen <code>_</code> enthält. Dieser wird von Typst in <code>\_</code> “escaped”, so dass der Pfad nicht als <code>_extensions/foobar/MeinLogo.png</code> sonder als <code>\_extensions/foobar/MeinLogo.png</code> erkannt wird. Um dies wieder rückgängig zu machen, kann innerhalb der <code>.typ</code>-Dateien die Funktion <code>OBJEKT.replace("\\", "")</code> verwendet werden.</p>
<p>Zunächst greifen wir den Logopfad in der Datei <code>typst-show.typ</code> ab.</p>
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>typst-show.typ</strong></pre>
</div>
<div class="sourceCode" id="cb12" data-filename="typst-show.typ" style="background: #f1f3f5;"><pre class="sourceCode latex code-with-copy"><code class="sourceCode latex"><span id="cb12-1">#show: foobar.with(</span>
<span id="cb12-2">  <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">$if(title)$</span></span>
<span id="cb12-3">    meintitel: "<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">$title$</span>",</span>
<span id="cb12-4">  <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">$endif$</span></span>
<span id="cb12-5">  <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">$if(logo)$</span></span>
<span id="cb12-6">    logo: "<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">$logo$</span>",</span>
<span id="cb12-7">  <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">$endif$</span></span>
<span id="cb12-8">)</span></code></pre></div>
</div>
<p>In der Datei <code>typst-template.typ</code> melden wir die Variable <code>logo</code> an und reparieren den kaputten Pfad.</p>
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>typst-template.typ</strong></pre>
</div>
<div class="sourceCode" id="cb13" data-filename="typst-template.typ" style="background: #f1f3f5;"><pre class="sourceCode rust code-with-copy"><code class="sourceCode rust"><span id="cb13-1">#let foobar(</span>
<span id="cb13-2">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Welche Werte erwartet mein Template?</span></span>
<span id="cb13-3">  meintitel<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Du hast den Titel vergessen"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb13-4">  logo<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> none<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb13-5">  body</span>
<span id="cb13-6">) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb13-7">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Hier beginnt die Ausgabe</span></span>
<span id="cb13-8"></span>
<span id="cb13-9">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Logo-Pfad escapen</span></span>
<span id="cb13-10">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">let</span> logo_path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> logo<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>replace(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>)</span>
<span id="cb13-11">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Logo anzeigen</span></span>
<span id="cb13-12">  image(logo_path<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> width<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> 70mm)</span>
<span id="cb13-13"></span>
<span id="cb13-14">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// title anzeigen</span></span>
<span id="cb13-15">  text(36pt)[#meintitel]</span>
<span id="cb13-16"></span>
<span id="cb13-17">  body</span>
<span id="cb13-18"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span></code></pre></div>
</div>
</section>
<section id="ausgabe-stylen" class="level3">
<h3 class="anchored" data-anchor-id="ausgabe-stylen">Ausgabe stylen</h3>
<p>Auf diese Weise erweitere ich meine Extension nach und nach, so dass alles nach meinen Wünschen ausgegeben wird.</p>
<p>Wie man genau die Seiteneigenschaften (DIN-A4, deutsche Sprache, Kopf- und Fußzeilen, etc.) beeinflusst, habe ich in der Typst-Dokumentation nachgelesen, siehe <a href="https://typst.app/docs/" class="uri">https://typst.app/docs/</a>. Sehr hilfreich war für mich deren <a href="https://typst.app/docs/guides/guide-for-latex-users/">Guide for LaTeX users</a>.</p>
</section>
</section>
<section id="beispiel" class="level2">
<h2 class="anchored" data-anchor-id="beispiel">Beispiel</h2>
<p>Herausgekommen ist beispielsweise diese simple Extension, die ich für Aushänge an der Hochschule nutze. Sie nimmt die Parameter <code>title</code> und <code>logo</code> entgegen. In der Kopfzeile wird rechts das Logo ausgegeben, und links ein schöner blauer Kasten mit dem <code>title</code> in weißer Schrift.</p>
<p>In unserer <code>foobar</code>-Extension müssen die Dateien wie folgt geändert werden:</p>
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>_extension.yml</strong></pre>
</div>
<div class="sourceCode" id="cb14" data-filename="_extension.yml" style="background: #f1f3f5;"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb14-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">title</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> Foobar</span></span>
<span id="cb14-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">author</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> Joe Slam</span></span>
<span id="cb14-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">version</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.0.0</span></span>
<span id="cb14-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">quarto-required</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"&gt;=1.5.0"</span></span>
<span id="cb14-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">contributes</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb14-6"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">formats</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb14-7"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">typst</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb14-8"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">logo</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> MeinLogo.png</span></span>
<span id="cb14-9"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lang</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> de</span></span>
<span id="cb14-10"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">font</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Times New Roman"</span></span>
<span id="cb14-11"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">font-size</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> 12pt</span></span>
<span id="cb14-12"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">template-partials</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb14-13"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> typst-template.typ</span></span>
<span id="cb14-14"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> typst-show.typ</span></span></code></pre></div>
</div>
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>typst-show.typ</strong></pre>
</div>
<div class="sourceCode" id="cb15" data-filename="typst-show.typ" style="background: #f1f3f5;"><pre class="sourceCode latex code-with-copy"><code class="sourceCode latex"><span id="cb15-1">#show: foobar.with(</span>
<span id="cb15-2">    // Diese Werte kommen aus dem YAML</span>
<span id="cb15-3">    title: "<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">$title$</span>",</span>
<span id="cb15-4">    lang: "<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">$lang$</span>",</span>
<span id="cb15-5">    logo: "<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">$logo$</span>",</span>
<span id="cb15-6">    font: "<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">$font$</span>",</span>
<span id="cb15-7">    font-size: <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">$font-size$</span>,</span>
<span id="cb15-8">)</span></code></pre></div>
</div>
<div class="code-with-filename">
<div class="code-with-filename-file">
<pre><strong>typst-template.typ</strong></pre>
</div>
<div class="sourceCode" id="cb16" data-filename="typst-template.typ" style="background: #f1f3f5;"><pre class="sourceCode rust code-with-copy"><code class="sourceCode rust"><span id="cb16-1">#let foobar(</span>
<span id="cb16-2">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// welche Wert werden aus dem YAML-Header gelesen?</span></span>
<span id="cb16-3">  title<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> none<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb16-4">  logo<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> none<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb16-5">  lang<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> none<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb16-6">  font<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> none<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb16-7">  font<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> none<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb16-8">  body</span>
<span id="cb16-9">) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb16-10"></span>
<span id="cb16-11">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Hier startet die eigentliche Funktion</span></span>
<span id="cb16-12"></span>
<span id="cb16-13">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Der Logo-Pfad muss escaped werden</span></span>
<span id="cb16-14">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">let</span> logo_path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> logo<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>replace(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>)</span>
<span id="cb16-15"></span>
<span id="cb16-16">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Schriftart und Sprache einstellen</span></span>
<span id="cb16-17">  set text(font<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> font<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb16-18">           size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> font<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb16-19">           lang<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> lang<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span>)</span>
<span id="cb16-20">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Blockschrift aktivieren</span></span>
<span id="cb16-21">  set par(justify<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">true</span>)</span>
<span id="cb16-22">  </span>
<span id="cb16-23">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Farben definieren</span></span>
<span id="cb16-24">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">let</span> HSNRblue1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> rgb(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"185191"</span>)</span>
<span id="cb16-25">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">let</span> HSNRblue2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> rgb(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"07A1E2"</span>)</span>
<span id="cb16-26"></span>
<span id="cb16-27">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Seitengröße und -ränder festlegen</span></span>
<span id="cb16-28">  set page(width<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> 210mm<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb16-29">           height<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> 297mm<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb16-30">           margin<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> (top<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> 30mm<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> bottom<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> 30mm<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> left<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> 20mm<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> right<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> 20mm)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb16-31">           numbering<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb16-32">           number<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>align<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> center<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb16-33">           <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Kopfzeile</span></span>
<span id="cb16-34">           header<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> grid(</span>
<span id="cb16-35">                        columns<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> (1fr<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> 1fr)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb16-36">                        align<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> (left<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> right)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb16-37">                          rect(fill<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> HSNRblue1<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb16-38">                               width<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">70</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%,</span></span>
<span id="cb16-39">                               outset<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> (x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> 54pt))[#text(white<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> 18pt)[#title]]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb16-40">                          image(logo_path<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> width<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> 70mm)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb16-41">           )<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb16-42">           <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Fußzeile</span></span>
<span id="cb16-43">           footer<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> align(center)[#context counter(page)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>display(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1 von 1"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span>both<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">true</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span>)]</span>
<span id="cb16-44">  )</span>
<span id="cb16-45"></span>
<span id="cb16-46">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Abstand zwischen Header und Body</span></span>
<span id="cb16-47">  v(5mm)</span>
<span id="cb16-48"></span>
<span id="cb16-49">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Hauptteil des Dokuments</span></span>
<span id="cb16-50">  body</span>
<span id="cb16-51"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span></code></pre></div>
</div>
<p>Das sieht dann so aus:</p>
<p><img src="https://www.produnis.de/blog/posts/2024-11-16-quarto-typst-extension/aushangtypst.webp" class="img-fluid" width="250"></p>
<p>Zudem habe ich meine <code>quarto-letter</code>-Extension auf typst angepasst und bei Github veröffentlicht, siehe <a href="https://github.com/produnis/quarto-letter" class="uri">https://github.com/produnis/quarto-letter</a>.</p>
<p><img src="https://www.produnis.de/blog/posts/2024-11-16-quarto-typst-extension/quartolettertypst.webp" class="img-fluid" width="250"></p>
</section>
<section id="weblinks" class="level2">
<h2 class="anchored" data-anchor-id="weblinks">Weblinks</h2>
<ul>
<li><a href="https://typst.app/docs" class="uri">https://typst.app/docs</a></li>
<li><a href="https://quarto.org/docs/output-formats/typst.html" class="uri">https://quarto.org/docs/output-formats/typst.html</a></li>
<li><a href="https://quarto.org/docs/output-formats/typst-custom.html" class="uri">https://quarto.org/docs/output-formats/typst-custom.html</a></li>
<li><a href="https://qwinsi.github.io/tex2typst-webapp/" class="uri">https://qwinsi.github.io/tex2typst-webapp/</a></li>
<li><a href="https://www.produnis.de/blog/posts/2022-09-12-quarto-briefvorlage/" class="uri">https://www.produnis.de/blog/posts/2022-09-12-quarto-briefvorlage/</a></li>
<li><a href="https://nrennie.rbind.io/blog/pdf-quarto/making-pdf-with-quarto-typst-latex/" class="uri">https://nrennie.rbind.io/blog/pdf-quarto/making-pdf-with-quarto-typst-latex/</a></li>
<li><a href="https://typst.app/docs/guides/guide-for-latex-users/" class="uri">https://typst.app/docs/guides/guide-for-latex-users/</a></li>
<li><a href="https://github.com/quarto-dev/quarto-cli/discussions/11364" class="uri">https://github.com/quarto-dev/quarto-cli/discussions/11364</a></li>
<li><a href="https://github.com/quarto-dev/quarto-cli/discussions/11392" class="uri">https://github.com/quarto-dev/quarto-cli/discussions/11392</a></li>
<li><a href="https://github.com/produnis/quarto-letter" class="uri">https://github.com/produnis/quarto-letter</a></li>
</ul>
            <br><center>
            <div class="matrixfoot" id="matrixfooter">
            <a href="https://matrix.to/#/#produnis-blog:tchncs.de">
            <img src="https://www.produnis.de/images/Matrix.webp" width="60">
            </a>
            Diskussion per Matrix unter <a href="https://matrix.to/#/#produnis-blog:tchncs.de">https://matrix.to/#/#produnis-blog:tchncs.de</a>
            </div>
            </center><br>&nbsp;
        


</section>

 ]]></description>
  <category>quarto</category>
  <category>typst</category>
  <category>ubuntuusers</category>
  <guid>https://www.produnis.de/blog/posts/2024-11-16-quarto-typst-extension/</guid>
  <pubDate>Sat, 16 Nov 2024 13:33:00 GMT</pubDate>
  <media:content url="https://www.produnis.de/blog/posts/2024-11-16-quarto-typst-extension/quartotypst.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Hexsticker unter R erstellen</title>
  <dc:creator>Joe Slam</dc:creator>
  <link>https://www.produnis.de/blog/posts/2024-07-24-hexsticker/</link>
  <description><![CDATA[ 





<p>Die Welt von R hat viele faszinierende Aspekte, aber einer der sichtbarsten und vielleicht auch der buntesten sind die Hexsticker. Diese kleinen, sechseckigen Aufkleber sind mehr als nur Dekoration – sie sind ein Symbol für die Community, die Leidenschaft und die Kreativität, die in der R-Welt steckt. Die Magie der Hexsticker</p>
<p>Ich war Anfang Juli auf der <em>useR2024</em> in Salzburg, und wenn man auf so eine Konferenz geht, merkt man schnell, dass Hexsticker überall zu finden sind. Doch es geht nicht nur um das Sammeln – jeder Hexsticker erzählt eine Geschichte. Manche Sticker gibt es nur, wenn man einen bestimmten Vortrag oder Workshop besucht, andere bekommt man nur dann, wenn man eine Frage bei einer Postersession stellt. Es wird fast zu einer Art Schatzsuche, bei der man sich besonders fühlt, wenn man einen seltenen Sticker ergattert.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.produnis.de/blog/posts/2024-07-24-hexsticker/stickers.webp" class="img-fluid figure-img"></p>
<figcaption>Sticker-Beute</figcaption>
</figure>
</div>
<p>Inspiriert von dieser Stickerjagd und dem allgemeinen Enthusiasmus habe ich mich entschlossen, für meine eigenen R-Pakete auch solche Hexlogos zu erstellen.</p>
<section id="eigene-hexsticker-erzeugen" class="level2">
<h2 class="anchored" data-anchor-id="eigene-hexsticker-erzeugen">eigene Hexsticker erzeugen</h2>
<p>In R gibt es dafür ein eigenes Paket, das <a href="https://github.com/GuangchuangYu/hexSticker"><code>{hexSticker}</code></a> heisst.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Paket installieren</span></span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">install.packages</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"hexSticker"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">dependencies =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span></code></pre></div>
</div>
<p>Der grundlegende Aufruf lautet</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sticker</span>(BILD, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">package=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PAKETNAME"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">filename=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Sticker.png"</span>)</span></code></pre></div>
</div>
<p>Dabei kann das Aussehen über mehrere Parameter verändert werden:</p>
<ul>
<li><p><code>s_x</code>, <code>s_y</code> Position des Bildes</p></li>
<li><p><code>s_width</code>, <code>s_height</code> Größe des Bildes</p></li>
<li><p><code>p_x</code>, <code>p_y</code> Position des Paketnamens</p></li>
<li><p><code>p_color</code>, <code>p_family</code>, <code>p_fontaface</code>, <code>p_size</code> Texteigenschaften des Paketnamens</p></li>
<li><p><code>h_fill</code>, <code>h_color</code> Rahmen- und Füllfarben des Hexagon</p></li>
<li><p><code>h_size</code> Größe des Hexagon</p></li>
<li><p><code>url</code> optionale Webadresse</p></li>
<li><p><code>u_x</code>, <code>u_y</code> Position der URL</p></li>
<li><p><code>u_color</code>, <code>u_family</code>, <code>u_angle</code>, <code>u_size</code> Texteigenschaften der URL</p></li>
</ul>
<p>Das <code>BILD</code> kann ein R-Plot oder eine Bilddatei sein.</p>
<p>Für <a href="https://www.produnis.de/R">mein R-Buch</a> habe ich so folgenden Sticker erzeugt:</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(hexSticker)</span>
<span id="cb3-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(ggplot2)</span>
<span id="cb3-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># lade Daten</span></span>
<span id="cb3-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">load</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">url</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://www.produnis.de/R/data/epa.RData"</span>))</span>
<span id="cb3-5"></span>
<span id="cb3-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># plotten</span></span>
<span id="cb3-7">titelbild <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ggplot</span>(epa) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">x=</span>age) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">geom_histogram</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">aes</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">after_stat</span>(density)),</span>
<span id="cb3-10">                 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">lwd=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.3</span>,</span>
<span id="cb3-11">                 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#8a658a"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-12">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stat_density</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">geom=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"area"</span>,</span>
<span id="cb3-13">               <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"blue"</span>,</span>
<span id="cb3-14">               <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"seagreen3"</span>,</span>
<span id="cb3-15">               <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dotted"</span>,</span>
<span id="cb3-16">               <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">alpha=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-17">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stat_function</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fun=</span>dnorm,</span>
<span id="cb3-18">                <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">args=</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mean=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mean</span>(epa<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>age),<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sd=</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sd</span>(epa<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>age))),</span>
<span id="cb3-19">                <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">color =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"red"</span>,</span>
<span id="cb3-20">                <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">linetype =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dashed"</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span></span>
<span id="cb3-21">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">theme_void</span>()</span>
<span id="cb3-22"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#----------------------------------------------------------------------</span></span>
<span id="cb3-23"></span>
<span id="cb3-24"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Sticker erzeugen</span></span>
<span id="cb3-25"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sticker</span>(titelbild, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">package=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"jgsbook"</span>, </span>
<span id="cb3-26">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p_color=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p_x=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p_size=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>,</span>
<span id="cb3-27">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">s_x=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.05</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">s_y=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.06</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">s_width=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.5</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">s_height=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.4</span>,</span>
<span id="cb3-28">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">h_fill=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#07A1E2"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">h_color=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#185191"</span>,</span>
<span id="cb3-29">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">url=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"produnis.de/R"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">u_size=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">u_color=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>,</span>
<span id="cb3-30">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">filename=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"jgsbook.png"</span>)</span></code></pre></div>
</div>
<div class="cell">
<div class="cell-output-display">
<div>
<figure class="figure">
<p><img src="https://www.produnis.de/blog/posts/2024-07-24-hexsticker/index_files/figure-html/unnamed-chunk-4-1.png" class="img-fluid figure-img" width="672"></p>
</figure>
</div>
</div>
</div>
<p>Und auch mein <a href="https://github.com/produnis/trainingslageR">trainingslageR</a> hat bereits einen Hexsticker. Hierfür habe ich allerdings das Hintergrundbild mit GIMP vorbereitet und dann “nur” eingelesen.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sticker</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trainingslageR-Vorlage2.png"</span>, </span>
<span id="cb4-2">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">package=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"t"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p_color=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p_x=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.7</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p_size=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.001</span>,</span>
<span id="cb4-3">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">s_x=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">s_y=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">s_width=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.02</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">s_height=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1.02</span>,</span>
<span id="cb4-4">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">h_fill=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">h_color=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#185191"</span>,</span>
<span id="cb4-5">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">url=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"github.com/produnis/trainingslager"</span>, </span>
<span id="cb4-6">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">u_size=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4.2</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">u_color=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">u_y=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.06</span>,</span>
<span id="cb4-7">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">filename=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"trainingslageR-hexsticker.png"</span>)</span></code></pre></div>
</div>
<p><img src="https://www.produnis.de/blog/posts/2024-07-24-hexsticker/trainingslageR-hexsticker.webp" class="img-fluid" width="250"></p>
</section>
<section id="weblinks" class="level2">
<h2 class="anchored" data-anchor-id="weblinks">Weblinks</h2>
<ul>
<li><a href="https://github.com/GuangchuangYu/hexSticker" class="uri">https://github.com/GuangchuangYu/hexSticker</a></li>
</ul>
            <br><center>
            <div class="matrixfoot" id="matrixfooter">
            <a href="https://matrix.to/#/#produnis-blog:tchncs.de">
            <img src="https://www.produnis.de/images/Matrix.webp" width="60">
            </a>
            Diskussion per Matrix unter <a href="https://matrix.to/#/#produnis-blog:tchncs.de">https://matrix.to/#/#produnis-blog:tchncs.de</a>
            </div>
            </center><br>&nbsp;
        


</section>

 ]]></description>
  <category>R</category>
  <category>ubuntuusers</category>
  <guid>https://www.produnis.de/blog/posts/2024-07-24-hexsticker/</guid>
  <pubDate>Wed, 24 Jul 2024 17:33:00 GMT</pubDate>
  <media:content url="https://www.produnis.de/blog/posts/2024-07-24-hexsticker/jgsbook-hexsticker.png" medium="image" type="image/png" height="167" width="144"/>
</item>
<item>
  <title>Auf der Konsole den Rechner neustarten (KDE Plasma)</title>
  <dc:creator>Joe Slam</dc:creator>
  <link>https://www.produnis.de/blog/posts/2024-06-16-plasmalogout/</link>
  <description><![CDATA[ 





<p>Ich habe seit ich denken kann zwei Aliase in meiner <code>.bashrc</code>:</p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">alias</span> neustarten=<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'sudo shutdown -r now'</span></span>
<span id="cb1-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">alias</span> ausschalten=<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'sudo shutdown -h now'</span></span></code></pre></div>
<p>So kann ich meinen PC ausschalten oder neustarten, und muss nicht viel tippen.</p>
<p>Diese Art des <code>shutdown</code> ist jedoch eher ungeeignet, und auch <code>systemctl reboot</code> und <code>systemctl poweroff</code> sind mit KDE-Plasma nicht ideal, da kein korrekter Logout aus der Plasmasession erfolgt, sondern die Kiste einfach alles abwürgt und runterfährt.</p>
<p>Um mich also <em>korrekt</em> aus Plasma abzumelden, und dann erst herunterzufahren, habe ich die Aliase entsprechend angepasst.</p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">alias</span> neustarten=<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"[[ -o login ]] &amp;&amp; logout || qdbus org.kde.Shutdown /Shutdown  org.kde.Shutdown.logoutAndReboot"</span></span>
<span id="cb2-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">alias</span> ausschalten=<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"[[ -o login ]] &amp;&amp; logout || qdbus org.kde.Shutdown /Shutdown  org.kde.Shutdown.logoutAndShutdown"</span></span>
<span id="cb2-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">alias</span> logout=<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"[[ -o login ]] &amp;&amp; logout || qdbus org.kde.Shutdown /Shutdown  org.kde.Shutdown.logout"</span></span></code></pre></div>
<p>Diese Variante dauert etwas länger, eben weil alles erst korrekt abgemeldet wird, führt aber genau das aus, was passieren würde, wenn ich mich per UI-Knopf abmelde oder den Rechner neustarte. Ich muss bei dieser Variante auch kein Passwort eingeben, da der Befehl ohne “<code>sudo</code>” auskommt (genau so wie die UI-Knöpfe).</p>
<p>Meine alten Aliase habe ich aber unter neuer Kennung beibehalten, aus nostalgischen Gründen, und falls ich mal außerhalb einer Plasmasitzung zügig rebooten will.</p>
<div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb3-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">alias</span> neustartenc=<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'sudo shutdown -r now'</span></span>
<span id="cb3-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">alias</span> ausschaltenc=<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'sudo shutdown -h now'</span></span></code></pre></div>
<section id="weblinks" class="level2">
<h2 class="anchored" data-anchor-id="weblinks">Weblinks</h2>
<ul>
<li><a href="https://discuss.kde.org/t/logout-reboot-and-shutdown-using-the-terminal/743/9" class="uri">https://discuss.kde.org/t/logout-reboot-and-shutdown-using-the-terminal/743/9</a></li>
</ul>
            <br><center>
            <div class="matrixfoot" id="matrixfooter">
            <a href="https://matrix.to/#/#produnis-blog:tchncs.de">
            <img src="https://www.produnis.de/images/Matrix.webp" width="60">
            </a>
            Diskussion per Matrix unter <a href="https://matrix.to/#/#produnis-blog:tchncs.de">https://matrix.to/#/#produnis-blog:tchncs.de</a>
            </div>
            </center><br>&nbsp;
        


</section>

 ]]></description>
  <category>KDE</category>
  <category>ubuntuusers</category>
  <guid>https://www.produnis.de/blog/posts/2024-06-16-plasmalogout/</guid>
  <pubDate>Sun, 16 Jun 2024 14:43:00 GMT</pubDate>
  <media:content url="https://www.produnis.de/blog/posts/2024-06-16-plasmalogout/2024.webp" medium="image" type="image/webp"/>
</item>
<item>
  <title>hollywood</title>
  <dc:creator>Joe Slam</dc:creator>
  <link>https://www.produnis.de/blog/posts/2024-06-07-hollywood/</link>
  <description><![CDATA[ 





<p>Mögt ihr auch diese Hacker-Szenen in Filmen, bei denen der Bildschirm der Nerds gezeigt wird? Der ist dann meist zugeballert mit seltsamen Fenstern, in denen die Post abgeht.</p>
<p>Falls ihr mal im Cafe oder in der Bahn flexen wollt, empfehle ich das <code>hollywood</code> Paket. Einmal gestartet, zaubert es herrlich melodramatisches Technogebabbel auf euren Bildschirm.</p>
<p>:-)</p>
<div class="quarto-video"><video id="video_shortcode_videojs_video1" class="video-js vjs-default-skin vjs-fluid" controls="" preload="auto" data-setup="{}" title=""><source src="hollywood.webm"></video></div>
<section id="weblinks" class="level2">
<h2 class="anchored" data-anchor-id="weblinks">Weblinks</h2>
<ul>
<li><a href="https://a.hollywood.computer/" class="uri">https://a.hollywood.computer/</a></li>
<li><a href="https://snapcraft.io/install/hollywood/ubuntu" class="uri">https://snapcraft.io/install/hollywood/ubuntu</a></li>
</ul>
            <br><center>
            <div class="matrixfoot" id="matrixfooter">
            <a href="https://matrix.to/#/#produnis-blog:tchncs.de">
            <img src="https://www.produnis.de/images/Matrix.webp" width="60">
            </a>
            Diskussion per Matrix unter <a href="https://matrix.to/#/#produnis-blog:tchncs.de">https://matrix.to/#/#produnis-blog:tchncs.de</a>
            </div>
            </center><br>&nbsp;
        


</section>

 ]]></description>
  <category>Linux</category>
  <category>ubuntuusers</category>
  <guid>https://www.produnis.de/blog/posts/2024-06-07-hollywood/</guid>
  <pubDate>Fri, 07 Jun 2024 13:44:00 GMT</pubDate>
  <media:content url="https://www.produnis.de/images/hollywood.webp" medium="image" type="image/webp"/>
</item>
<item>
  <title>iframe backgrounds auf quarto Folien</title>
  <dc:creator>Joe Slam</dc:creator>
  <link>https://www.produnis.de/blog/posts/2024-06-02-iframe-background/</link>
  <description><![CDATA[ 





<p>Ich baue fast alle meine Dokumente mit <a href="https://www.quarto.org">quarto</a>, seien es Briefe, Handouts, Artikel oder Folien. Für letztere bin ich über den <a href="https://emilhvitfeldt.github.io/quarto-iframe-examples/#/section">Beitrag von Emil Hvitfeldt</a> gestolpert. Er bindet <code>iframes</code> als Hintergrund ein, um animierte Folien zu erzeugen.</p>
<p>Passende Hintergrundanimationen finden sich dabei z.B. auf <a href="https://codepen.io">codepen.io</a> und auch im <a href="https://github.com/EmilHvitfeldt/quarto-iframe-examples">GitHub Repository von Emil</a>.</p>
<section id="iframe-einbinden" class="level2">
<h2 class="anchored" data-anchor-id="iframe-einbinden">iFrame einbinden</h2>
<ul>
<li>Im Verzeichnis der <code>.qmd</code>-Datei erstellt ihr einen weiteren Unterordner, und nennt ihn z.B. <code>iframes</code>.</li>
<li>Ladet ein passendes iframe herunter, z.B. von der <a href="https://github.com/EmilHvitfeldt/quarto-iframe-examples">GitHub-Seite von Emil Hvitfeldt</a>.</li>
<li>Den Ordner des iframes schiebt ihr in euren <code>iframes</code>-Ordner.</li>
<li>Hinter die Rauten einer neuen Folie schreibt ihr <code>{background-iframe="Pfad/zur/index.html"}</code>, also z.B.</li>
</ul>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">## title {background-iframe="iframes/meatballs/index.html"}</span></span></code></pre></div>
<ul>
<li>Im <code>YAML</code>-Header muss zudem der Parameter <code>preload-iframes: true</code> gesetzt werden.</li>
<li>Eine Beispieldatei könnte so aussehen:</li>
</ul>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">---</span></span>
<span id="cb2-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">title:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"iframe backgrounds"</span></span>
<span id="cb2-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">preload-iframes:</span> true</span>
<span id="cb2-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">format:</span></span>
<span id="cb2-5">  <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">revealjs:</span></span>
<span id="cb2-6">    <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">embed-resources:</span> true</span>
<span id="cb2-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">---</span></span>
<span id="cb2-8"></span>
<span id="cb2-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">## {.center .white background-iframe="iframes/ambient/index.html"}</span></span>
<span id="cb2-10"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:::</span> {.r-fit-text}</span>
<span id="cb2-11"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Ambient</span></span>
<span id="cb2-12"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:::</span></span>
<span id="cb2-13"></span>
<span id="cb2-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">## {.center background-iframe="iframes/moving-waves/index.html"}</span></span>
<span id="cb2-15"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:::</span> {.r-fit-text}</span>
<span id="cb2-16"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Moving</span> Waves</span>
<span id="cb2-17"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:::</span></span></code></pre></div>
<p>Das sieht dann in etwa so aus:</p>
<iframe width="700" height="400" src="../../../blog/images/2024/iframe-backgrounds.html" title="Beispiele"></iframe>
<p>(es kann uU etwas dauern, bis der Hintergrund sichtbar ist. Das ist lokal in der “echten” Präsentation aber nicht der Fall)</p>
</section>
<section id="nachteil" class="level2">
<h2 class="anchored" data-anchor-id="nachteil">Nachteil</h2>
<p>Einen Nachteil habe ich ebenfalls festgestellt: da die Hintergründe per iframe eingebunden werden, sind sie in der HTML-Präsentationsdatei selbst nicht enthalten, auch nicht, wenn der Parameter <code>embed-resources: true</code> gesetzt ist. Das heisst, man kann die Präsentationsdatei nicht “einfach so” weitergeben, weil dann die animierten Hintergründe nicht mehr funktionieren.</p>
<p>Wenn die Präsentation mittels <a href="https://github.com/astefanutti/decktape">decktape</a> in eine PDF-Datei umgewandelt wird, bleibt ein Screenshot des Hintergrunds erhalten.</p>
</section>
<section id="weblinks" class="level2">
<h2 class="anchored" data-anchor-id="weblinks">Weblinks</h2>
<ul>
<li><a href="https://emilhvitfeldt.github.io/quarto-iframe-examples/" class="uri">https://emilhvitfeldt.github.io/quarto-iframe-examples/</a></li>
<li><a href="https://github.com/EmilHvitfeldt/quarto-iframe-examples" class="uri">https://github.com/EmilHvitfeldt/quarto-iframe-examples</a></li>
<li><a href="https://quarto.org" class="uri">https://quarto.org</a></li>
<li><a href="https://github.com/astefanutti/decktape" class="uri">https://github.com/astefanutti/decktape</a></li>
</ul>
            <br><center>
            <div class="matrixfoot" id="matrixfooter">
            <a href="https://matrix.to/#/#produnis-blog:tchncs.de">
            <img src="https://www.produnis.de/images/Matrix.webp" width="60">
            </a>
            Diskussion per Matrix unter <a href="https://matrix.to/#/#produnis-blog:tchncs.de">https://matrix.to/#/#produnis-blog:tchncs.de</a>
            </div>
            </center><br>&nbsp;
        


</section>

 ]]></description>
  <category>quarto</category>
  <category>ubuntuusers</category>
  <guid>https://www.produnis.de/blog/posts/2024-06-02-iframe-background/</guid>
  <pubDate>Sun, 02 Jun 2024 11:21:00 GMT</pubDate>
  <media:content url="https://www.produnis.de/images/logos/quarto.png" medium="image" type="image/png" height="144" width="144"/>
</item>
<item>
  <title>Paarweise Chiquadrat-Test in R</title>
  <dc:creator>Joe Slam</dc:creator>
  <link>https://www.produnis.de/blog/posts/2024-05-24-pairwise-chisq-test/</link>
  <description><![CDATA[ 





<p>In R ist keine Funktion implementiert, die einen paarweisen Chiquadrat-Test durchführt. Das mag daran liegen, dass der Chiquadrat-Test als (weniger genaue) Alternative zu dem rechenaufwändigen exakten Fisher-Test entwickelt wurde. Mit der heutigen Computertechnologie ist es jedoch in den meisten Fällen kein Problem, den exakten Test nach Fisher auch auf älterer Hardware anzuwenden, siehe hierzu <a href="https://www.produnis.de/R/schliessende-statistik.html#sec-posthocsig" class="uri">https://www.produnis.de/R/schliessende-statistik.html#sec-posthocsig</a>.</p>
<section id="paarweise-chiquadrat-tests" class="level2">
<h2 class="anchored" data-anchor-id="paarweise-chiquadrat-tests">Paarweise Chiquadrat-Tests</h2>
<p>Ich habe aus edukativen Gründen eine Funktion programmiert, die dennoch paarweise Chiquadrat-Tests durchführt.</p>
<div class="callout callout-style-simple callout-tip">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-body-container">
<p>Die Funktion ist auch in meinem Zusatzpaket <code>jgsbook</code> enthalten und kann mittels <code>jgsbook::pairwise.chisq.test(x, y)</code> aufgerufen werden.</p>
</div>
</div>
</div>
<p>Durch die Mehrfachvergleiche (multiples Testen) entsteht das erhöhte Risiko von falsch-positiven Ergebnissen (Typ-I-Fehler). Bei unserer Funktion müssen wir das Problem der Mehrfachtestung berücksichtigen. In Zeile 50 übergeben wir die berechneten p-Werte der <code>p.adjust()</code>-Funktion, und korrigieren die Werte mit dem gewünschten Verfahren (standardmäßig <code>bonferroni</code>).</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource r number-lines code-with-copy"><code class="sourceCode r"><span id="cb1-1">pairwise.chisq.test <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(A, B, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p.adjust.method=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bonferroni"</span>){</span>
<span id="cb1-2">  </span>
<span id="cb1-3">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># wir überprüfen, ob die Objekte vom Typ factor sind.</span></span>
<span id="cb1-4">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.factor</span>(A) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is.factor</span>(B)) {</span>
<span id="cb1-5">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stop</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Both objects need to be factors."</span>)</span>
<span id="cb1-6">  }</span>
<span id="cb1-7"></span>
<span id="cb1-8">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># erstelle ein Hilfsdatenframe</span></span>
<span id="cb1-9">  df <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">A=</span>A, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">B=</span>B)</span>
<span id="cb1-10"></span>
<span id="cb1-11">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Erzeuge alle möglichen 2er-Kombinationen von B</span></span>
<span id="cb1-12">  kombi <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">combn</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">levels</span>(B), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb1-13"></span>
<span id="cb1-14">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Erzeuge ein Datenframe für die Werterückgabe</span></span>
<span id="cb1-15">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># die erste Zeile wird später wieder gelöscht.</span></span>
<span id="cb1-16">  result <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group1 =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A"</span>,</span>
<span id="cb1-17">                       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group2 =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"B"</span>,</span>
<span id="cb1-18">                       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xsquare =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"9"</span>,</span>
<span id="cb1-19">                       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">df =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"9999"</span>,</span>
<span id="cb1-20">                       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pvalue =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"9"</span>,</span>
<span id="cb1-21">                       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">padjust =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"9"</span>,</span>
<span id="cb1-22">                       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">adjust =</span> p.adjust.method,</span>
<span id="cb1-23">                       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sig =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>)</span>
<span id="cb1-24"></span>
<span id="cb1-25">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Berechne für jedes Paar</span></span>
<span id="cb1-26">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (i <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(kombi)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)) {</span>
<span id="cb1-27">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># füge die aktuelle Paarung in einem Datenframe zusammen</span></span>
<span id="cb1-28">    help <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbind</span>(df[df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>B<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span>kombi[,i][<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>],],</span>
<span id="cb1-29">                  df[df<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>B<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span>kombi[,i][<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>],])</span>
<span id="cb1-30">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># führe den Chi-Quadrat-Test durch</span></span>
<span id="cb1-31">    pups <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">chisq.test</span>(help<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>A, help<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>B)</span>
<span id="cb1-32">    </span>
<span id="cb1-33">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># setze das Signifikanz-Signal zurück</span></span>
<span id="cb1-34">    sig <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span></span>
<span id="cb1-35">    </span>
<span id="cb1-36">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># setze einen Punkt wenn p &lt; 0.055</span></span>
<span id="cb1-37">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">p.adjust</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(pups<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p.value), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> p.adjust.method, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n=</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(kombi)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.055</span>) {sig<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"."</span>}</span>
<span id="cb1-38">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># setze einen Stern wenn p &lt; 0.05</span></span>
<span id="cb1-39">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">p.adjust</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(pups<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p.value), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> p.adjust.method, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n=</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(kombi)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>)  {sig<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"*"</span>}</span>
<span id="cb1-40">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># setze zwei Sterne wenn p &lt; 0.01</span></span>
<span id="cb1-41">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">p.adjust</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(pups<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p.value), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> p.adjust.method, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n=</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(kombi)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.01</span>)  {sig<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"**"</span>}</span>
<span id="cb1-42">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># setze drei Sterne wenn p &lt; 0.001</span></span>
<span id="cb1-43">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">p.adjust</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(pups<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p.value), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> p.adjust.method, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n=</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(kombi)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.001</span>) {sig<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"***"</span>}</span>
<span id="cb1-44">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># speichere die Ergebnisse in ein Datenframe</span></span>
<span id="cb1-45">    loop <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group1 =</span> kombi[,i][<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>],</span>
<span id="cb1-46">                       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group2 =</span> kombi[,i][<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>],</span>
<span id="cb1-47">                       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xsquare =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(pups<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>statistic),</span>
<span id="cb1-48">                       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">df =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(pups<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>parameter),</span>
<span id="cb1-49">                       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">pvalue =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(pups<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p.value),</span>
<span id="cb1-50">                       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">padjust =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">p.adjust</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(pups<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>p.value), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">method =</span> p.adjust.method, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">n=</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(kombi)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)),</span>
<span id="cb1-51">                       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">adjust =</span> p.adjust.method,</span>
<span id="cb1-52">                       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sig =</span> sig</span>
<span id="cb1-53">    )</span>
<span id="cb1-54">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># füge die aktuellen Ergebnisse dem "result"-Objekt hinzu</span></span>
<span id="cb1-55">    result <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rbind</span>(result, loop)</span>
<span id="cb1-56">  }</span>
<span id="cb1-57">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Fertig mit allen Paarungen</span></span>
<span id="cb1-58">  </span>
<span id="cb1-59">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Entferne den Dummy-Eintrag </span></span>
<span id="cb1-60">  result <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> result[<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,]</span>
<span id="cb1-61">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Korrigiere die Zeilennummerierung</span></span>
<span id="cb1-62">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">row.names</span>(result) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">NULL</span></span>
<span id="cb1-63">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Gebe die Ergebnisse zurück</span></span>
<span id="cb1-64">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">return</span>(result)</span>
<span id="cb1-65">}</span>
<span id="cb1-66"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#----------------------------------------------------------------------#</span></span></code></pre></div>
</div>
<p>Die Funktion nimmt folgende Parameter entgegen:</p>
<ul>
<li><code>A</code>: die erste Variable, ein Faktor, welche die Zieldaten enthält (z.B. <code>Geschlecht</code>)</li>
<li><code>B</code>: die zweite Variable, ein Faktor, welcher die Gruppeneinteilung enthält (z.B. <code>Ort</code>)</li>
<li><code>p.adjust.method</code>: die Methode zur Alphafehler-Korrekur, standardmäßig “<code>bonferroni</code>”, es gehen aber auch “alle anderen”, wie zB <code>holm</code> oder <code>hochberg</code>.</li>
</ul>
<p>Als Ergebnis liefert uns die Funktion ein Datenframe zurück, mit den Einträgen:</p>
<ul>
<li>Name von Gruppe 1</li>
<li>Name von Gruppe 2</li>
<li>Teststatistik (xsquare)</li>
<li>Freiheitsgrade (df)</li>
<li>p-Wert des Chi-Quadrat-Test</li>
<li>adjustierter p-Wert (nach gewählter Methode)</li>
<li>die gewählte Methode zur p-Wert-Adjustierung</li>
<li>Signifikanz-Signal für die adjustierten p-Werte (<code>.</code>, <code>*</code>, <code>**</code>, <code>***</code>)</li>
</ul>
</section>
<section id="beispiel" class="level2">
<h2 class="anchored" data-anchor-id="beispiel">Beispiel</h2>
<p>Als Beispiel untersuchen wir im Datensatz <code>pf8</code>, ob sich die Geschlechter je nach Standort unterscheiden.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource r number-lines code-with-copy"><code class="sourceCode r"><span id="cb2-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># verwende pf8 Datensatz</span></span>
<span id="cb2-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">load</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">url</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://www.produnis.de/R/data/pf8.RData"</span>))</span>
<span id="cb2-3"></span>
<span id="cb2-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># führe exakten Test durch</span></span>
<span id="cb2-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pairwise.chisq.test</span>(pf8<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Geschlecht, pf8<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Standort)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>      group1    group2           xsquare df               pvalue              padjust     adjust sig
1     Rheine   Münster  1.10471703224467  2     0.57559066836014                    1 bonferroni    
2     Rheine      Bahn 0.484729064039409  2    0.784770051592051                    1 bonferroni    
3     Rheine Ladbergen  3.82435691920203  2    0.147758150572077                    1 bonferroni    
4     Rheine  Internet  14.0768553245862  2 0.000877505212656076  0.00877505212656076 bonferroni  **
5    Münster      Bahn                 0  1                    1                    1 bonferroni    
6    Münster Ladbergen  3.97980963867552  1   0.0460487671171598    0.460487671171598 bonferroni    
7    Münster  Internet   8.4878079618588  1  0.00357534323663839   0.0357534323663839 bonferroni   *
8       Bahn Ladbergen  2.85957778936492  1   0.0908313368796546    0.908313368796546 bonferroni    
9       Bahn  Internet  5.76636469124268  1   0.0163357933303218    0.163357933303218 bonferroni    
10 Ladbergen  Internet  16.0075693112762  1 6.30897415058098e-05 0.000630897415058098 bonferroni ***</code></pre>
</div>
</div>
<p>Es ist zu erkennen, dass sich die Geschlechterverteilungen zwischen den Standortvergleichen <code>Internet-Rheine</code>, <code>Internet-Münster</code> und <code>Internet-Landbergen</code> unterscheiden.</p>
<section id="vergleich-mit-fisher-test" class="level3">
<h3 class="anchored" data-anchor-id="vergleich-mit-fisher-test">Vergleich mit Fisher Test</h3>
<p>Vergleichen wir die Ergebnisse mit den exakten Fisher-Tests:</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource r number-lines code-with-copy"><code class="sourceCode r"><span id="cb4-1">reporttools<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pairwise.fisher.test</span>(pf8<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Geschlecht, </span>
<span id="cb4-2">                                  pf8<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Standort, </span>
<span id="cb4-3">                                  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">p.adjust.method =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bonferroni"</span>)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>
    Pairwise comparisons using 

data:  pf8$Geschlecht and pf8$Standort 

          Rheine  Münster Bahn    Ladbergen
Münster   1.00000 -       -       -        
Bahn      1.00000 1.00000 -       -        
Ladbergen 1.00000 0.40161 0.64522 -        
Internet  0.00292 0.02852 0.13207 0.00065  

P value adjustment method: bonferroni </code></pre>
</div>
</div>
<p>Es ist erkennbar, dass beide Tests zwar in die selbe Richtung tendieren, und auch die gleichen Signifikanzbewertungen ausgeben. Jedoch sind die p-Werte mit unter deutlich abweichend.</p>
<div class="callout callout-style-simple callout-important">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-body-container">
<p>Unsere Funktion ist eine nette Übung. Am Besten ist es aber, immer den exakten Fisher-Test zu rechnen!</p>
</div>
</div>
</div>
</section>
</section>
<section id="weblinks" class="level2">
<h2 class="anchored" data-anchor-id="weblinks">Weblinks</h2>
<ul>
<li><a href="https://www.produnis.de/R/schliessende-statistik.html#sec-posthocsig" class="uri">https://www.produnis.de/R/schliessende-statistik.html#sec-posthocsig</a></li>
<li><a href="https://cran.r-project.org/web/packages/jgsbook/index.html" class="uri">https://cran.r-project.org/web/packages/jgsbook/index.html</a></li>
</ul>
            <br><center>
            <div class="matrixfoot" id="matrixfooter">
            <a href="https://matrix.to/#/#produnis-blog:tchncs.de">
            <img src="https://www.produnis.de/images/Matrix.webp" width="60">
            </a>
            Diskussion per Matrix unter <a href="https://matrix.to/#/#produnis-blog:tchncs.de">https://matrix.to/#/#produnis-blog:tchncs.de</a>
            </div>
            </center><br>&nbsp;
        


</section>

 ]]></description>
  <category>R</category>
  <guid>https://www.produnis.de/blog/posts/2024-05-24-pairwise-chisq-test/</guid>
  <pubDate>Fri, 24 May 2024 15:48:00 GMT</pubDate>
  <media:content url="https://www.produnis.de/images/logos/GNUR.png" medium="image" type="image/png" height="144" width="144"/>
</item>
<item>
  <title>Dynamisches DNS mit ddclient aktualisieren</title>
  <dc:creator>Joe Slam</dc:creator>
  <link>https://www.produnis.de/blog/posts/2024-03-31-ddclient/</link>
  <description><![CDATA[ 





<p>Mein Heimserver ist seit Jahren über eine dynamische-DNS-Adresse von spDYN per SSH erreichbar. Da ich einer der letzten glücklichen kleinen Lichter bin, die noch eine echte IP4-Adresse erhalten (und keine genattete), kann ich mich so immer von überall auf meine Kiste einloggen.</p>
<p>Bislang habe ich meine aktuellen IP-Adressen <a href="../2023-10-03-spdns-ipv6/">mittels Script</a> geupdatet. Im Zuge notwendiger Aktualisierungen bin ich über <a href="https://github.com/ddclient/ddclient">ddclient</a> gestolpert und nutze es seit dem ausschließlich - <a href="../2023-10-03-spdns-ipv6/">mein Script</a> ist in Rente gegangen.</p>
<section id="ddclient" class="level2">
<h2 class="anchored" data-anchor-id="ddclient">ddclient</h2>
<p>ddclient ist ein Perl-Client, der dynamische DNS-Einträge für Konten vieler dynamischer DNS-Dienste aktualisieren kann. Auf der <a href="https://github.com/ddclient/ddclient">Github-Seite</a> steht eine Liste der kompatiblen Dienste bereit, viele weitere Dienste funktionieren aber ebenfalls, da sie die selben Protokolle verwenden.</p>
<p>Ich nutze ddclient mit folgenden freien DynDNS-Anbietern:</p>
<ul>
<li><a href="https://www.duckdns.org">DuckDNS</a></li>
<li><a href="https://www.dynv6.com">Dynv6.com</a></li>
<li><a href="https://spdyn.de">spDYN</a> (nimmt keine neuen User auf)</li>
</ul>
<p>Da ich einen echten Dual-Stack habe, sollen IPv4 und IPv6 gleichzeitig aktualisiert werden.</p>
<section id="installation" class="level3">
<h3 class="anchored" data-anchor-id="installation">Installation</h3>
<p>ddclient kann installiert werden mittels:</p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Ubuntu</span></span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> apt-get install ddclient</span>
<span id="cb1-3"></span>
<span id="cb1-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Arch, btw</span></span>
<span id="cb1-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">pacman</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-S</span> ddclient</span></code></pre></div>
</section>
</section>
<section id="konfiguration" class="level2">
<h2 class="anchored" data-anchor-id="konfiguration">Konfiguration</h2>
<section id="systemd" class="level3">
<h3 class="anchored" data-anchor-id="systemd">systemd</h3>
<p>Ich bereite mir ein Systemd-Skellet vor, so dass ich alle <code>.conf</code>-Dateien im Verzeichnis <code>/etc/ddclient/</code> steuern kann.</p>
<p><code>sudo nano /etc/systemd/system/ddclient@.service</code></p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">[Unit]</span></span>
<span id="cb2-2"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">Documentation</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>man:ddclient<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">8</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span></span>
<span id="cb2-3"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">Description</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>Update <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">dynamic</span> domain name service entries</span>
<span id="cb2-4"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">After</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>network-online.target</span>
<span id="cb2-5"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">Wants</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>network-online.target</span>
<span id="cb2-6"></span>
<span id="cb2-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">[Service]</span></span>
<span id="cb2-8"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">Type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>forking</span>
<span id="cb2-9"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">Environment</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>daemon_interval=10m</span>
<span id="cb2-10"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">EnvironmentFile</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>-/etc/default/ddclient</span>
<span id="cb2-11"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">ExecStart</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>/sbin/ddclient <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">-syslog</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-file</span> /etc/ddclient/%I.conf <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-cache</span> /var/cache/ddclient/%I.cache</span>
<span id="cb2-12"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">Restart</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>on-failure</span>
<span id="cb2-13"></span>
<span id="cb2-14"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">[Install]</span></span>
<span id="cb2-15"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">WantedBy</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>multi-user.target</span></code></pre></div>
<p>Jetzt müssen die Services neu geladen werden,…</p>
<p><code>sudo systemctl daemon-reload</code></p>
<p>…und schon kann es losgehen. Alle <code>FOO.conf</code>-Dateien im Verzeichnis <code>/etc/ddclient</code> lassen sich nun steuern mittels <code>systemctl start ddclient@FOO</code> (ohne <code>.conf</code>).</p>
<p>Dafür müssen wir aber diese Config-Dateien erstellen, und wir sollten wissen, wie wir unsere “echten” globalen IPv4 und IPv6-Adressen abrufen können.</p>
</section>
<section id="ip-adressen-abrufen" class="level3">
<h3 class="anchored" data-anchor-id="ip-adressen-abrufen">IP-Adressen abrufen</h3>
<p>ddclient kann die Adressen entweder über die Interfaceschnittstelle oder über das Web beziehen. Das führt bei mir allerdings zu Probleme:</p>
<ul>
<li>über die Interface-Schnittstelle (z.B. <code>eth0</code>) finde ich nur meine lokal LAN-IP (weil ich hinter meiner FritzBox sitze)</li>
<li>über die <code>web</code>-Methode finde ich nur eine IPv6-Adresse, nicht aber meine IPv4.</li>
</ul>
<p>Daher muss ich sicherstellen, dass für IPv4 wirklich die gültige IPv4 gefunden wird, und für IPv6 ebenso. Ich kann diese externen IP-Adressen mittels <code>curl</code> abrufen:</p>
<div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb3-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># externe IPv4</span></span>
<span id="cb3-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">curl</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-s4</span> http://ifconfig.me/ip</span>
<span id="cb3-3"></span>
<span id="cb3-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># externe IPv6</span></span>
<span id="cb3-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">curl</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-s6</span> http://ifconfig.me/ip</span></code></pre></div>
<p>Dies mache ich mir in ddclient zu nutze, denn neben “Interface” und “Web” kann über den Parameter <code>cmd=&lt;PROGRAM&gt;</code> ein custom Script angegeben werden, welches die IP-Adressen ermittelt. Ich erzeuge mir diese Scripte jeweils für IPv4 und IPv6 direkt im Verzeichnis <code>/etc/ddclient</code>.</p>
<p><code>sudo nano /etc/ddclient/myipv4address.sh</code></p>
<div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb4-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">curl</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-s4</span> http://ifconfig.me/ip</span></code></pre></div>
<p><code>sudo nano /etc/ddclient/myipv6address.sh</code></p>
<div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb5-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">curl</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-s6</span> http://ifconfig.me/ip</span></code></pre></div>
<p>Die Scriptdateien müssen noch ausführbar gemacht werden: <code>sudo chmod +x /etc/ddclient/myipv6address.sh /etc/ddclient/myipv4address.sh</code></p>
</section>
<section id="ddclient-für-meinen-anbieter-konfigurieren" class="level3">
<h3 class="anchored" data-anchor-id="ddclient-für-meinen-anbieter-konfigurieren">ddclient für meinen Anbieter konfigurieren</h3>
<p>Für jeden DynDNS-Dienst lege ich mir eine eigene Config-Datei an. So sieht z.B. meine Client-Config für <a href="https://www.duckdns.org">DuckDNS</a> aus:</p>
<p><code>sudo nano /etc/ddclient/duckdns.conf</code></p>
<div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb6-1"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">daemon</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>300                       <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># check every 300 seconds</span></span>
<span id="cb6-2"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">syslog</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>yes                       <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># log update msgs to syslog</span></span>
<span id="cb6-3"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">pid</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>/var/run/ddclientduckdns.pid <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># record PID in file.</span></span>
<span id="cb6-4"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">ssl</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>yes                          <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># use ssl-support.</span></span>
<span id="cb6-5"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">debug</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>yes                        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># write to journal log</span></span>
<span id="cb6-6"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">verbose</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>yes                      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># write to journal log</span></span>
<span id="cb6-7"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">usev4</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>cmdv4, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">cmdv4</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>/etc/ddclient/myipv4address.sh <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># IPv4</span></span>
<span id="cb6-8"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">usev6</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>cmdv6, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">cmdv6</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>/etc/ddclient/myipv6address.sh <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># IPv6</span></span>
<span id="cb6-9"></span>
<span id="cb6-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#### DUCKDNS.org ########</span></span>
<span id="cb6-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#------------------------</span></span>
<span id="cb6-12"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">protocol</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>duckdns,    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Komma muss bleiben</span></span>
<span id="cb6-13"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">password</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>9a5dc6a5-FUCK-AFD-bbaf-foobar <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ersetze dein Token</span></span>
<span id="cb6-14"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">YOURNAME.duckdns.org</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># deinen Namen ersetzen</span></span></code></pre></div>
<p>Für <a href="https://www.dynv6.com">Dynv6.com</a> sieht diese so aus:</p>
<p><code>sudo nano /etc/ddclient/dynv6.conf</code></p>
<div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb7-1"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">daemon</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>300                     <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># check every 300 seconds</span></span>
<span id="cb7-2"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">syslog</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>yes                     <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># log update msgs to syslog</span></span>
<span id="cb7-3"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">pid</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>/var/run/ddclientdynv6.pid <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># record PID in file.</span></span>
<span id="cb7-4"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">ssl</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>yes                        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># use ssl-support.</span></span>
<span id="cb7-5"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">debug</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>yes                      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># write to journal log</span></span>
<span id="cb7-6"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">verbose</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>yes                    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># write to journal log</span></span>
<span id="cb7-7"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">usev4</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>cmdv4, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">cmdv4</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>/etc/ddclient/myipv4address.sh <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># für IPv4</span></span>
<span id="cb7-8"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">usev6</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>cmdv6, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">cmdv6</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>/etc/ddclient/myipv6address.sh <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># für IPv6</span></span>
<span id="cb7-9"></span>
<span id="cb7-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#### DYNv6.com ##########</span></span>
<span id="cb7-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#------------------------</span></span>
<span id="cb7-12"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">protocol</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>dyndns2</span>
<span id="cb7-13"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">server</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>dynv6.com</span>
<span id="cb7-14"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">password</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'sKx3hF_stPT_fuck_AfD_1rPmskxiTga'</span> </span>
<span id="cb7-15"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">login</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>none</span>
<span id="cb7-16"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">YOURNAME.dynv6.net</span></span></code></pre></div>
</section>
</section>
<section id="ddclient-starten" class="level2">
<h2 class="anchored" data-anchor-id="ddclient-starten">ddclient starten</h2>
<p>Zunächst können die Einstellungen getestet werden, ohne Daten zum Server zu senden:</p>
<p><code>ddclient -daemon=0 -debug -verbose -noquiet -file /etc/ddclient/dynv6.conf</code></p>
<p>Sieht alles gut aus, können wir die Dienste wie folgt aktivieren:</p>
<div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb8-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># aktivieren und starten</span></span>
<span id="cb8-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> systemctl enable <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--now</span> ddclient@duckdns</span>
<span id="cb8-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> systemctl enable <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--now</span> ddclient@dynv6</span>
<span id="cb8-4"></span>
<span id="cb8-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Logs ansehen</span></span>
<span id="cb8-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">journalctl</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-u</span> ddclient@duckdns <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-f</span></span>
<span id="cb8-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">journalctl</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-u</span> ddclient@dynv6 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-f</span></span></code></pre></div>
<p>Tolle Sache, funktioniert prima!</p>
</section>
<section id="weblinks" class="level2">
<h2 class="anchored" data-anchor-id="weblinks">Weblinks</h2>
<ul>
<li><a href="https://github.com/ddclient/ddclient" class="uri">https://github.com/ddclient/ddclient</a></li>
<li><a href="https://dynv6.com/" class="uri">https://dynv6.com/</a></li>
<li><a href="https://www.duckdns.org" class="uri">https://www.duckdns.org</a></li>
<li><a href="https://wiki.ubuntuusers.de/Archiv/DDNS-Clients/" class="uri">https://wiki.ubuntuusers.de/Archiv/DDNS-Clients/</a></li>
<li><a href="https://wiki.archlinux.org/title/Dynamic_DNS" class="uri">https://wiki.archlinux.org/title/Dynamic_DNS</a></li>
</ul>
            <br><center>
            <div class="matrixfoot" id="matrixfooter">
            <a href="https://matrix.to/#/#produnis-blog:tchncs.de">
            <img src="https://www.produnis.de/images/Matrix.webp" width="60">
            </a>
            Diskussion per Matrix unter <a href="https://matrix.to/#/#produnis-blog:tchncs.de">https://matrix.to/#/#produnis-blog:tchncs.de</a>
            </div>
            </center><br>&nbsp;
        


</section>

 ]]></description>
  <category>ddclient</category>
  <category>Heimserver</category>
  <category>IPv6</category>
  <category>ubuntuusers</category>
  <guid>https://www.produnis.de/blog/posts/2024-03-31-ddclient/</guid>
  <pubDate>Sun, 31 Mar 2024 18:00:00 GMT</pubDate>
  <media:content url="https://www.produnis.de/blog/posts/2024-03-31-ddclient/DuckDNS.webp" medium="image" type="image/webp"/>
</item>
<item>
  <title>Ein privates Netz mit Wireguard erstellen</title>
  <dc:creator>Joe Slam</dc:creator>
  <link>https://www.produnis.de/blog/posts/2024-03-22-wireguard/</link>
  <description><![CDATA[ 





<p>In den <a href="../2024-03-16-openvpn/">letzten</a> <a href="../2024-03-19-openvpn-android/">Blogposts</a> habe ich gezeigt, wie ich mein privates VPN mit openVPN aufsetze. In diesem Post wiederhole ich das - nur eben mit Wireguard.</p>
<p>OpenVPN und Wireguard können auch problemlos nebeneinander laufen, wenn sie verschiedene Netzmasken benutzen. So hat man jeweils ein Fall-Back-Netz, mit dem man die Clients noch erreichen kann.</p>
<p>Auf dem Handy verbraucht openVPN mehr Strom, weil die Kryptosachen stärker sind. Wireguard ist da schlanker bei ausreichender Verschlüsselung.</p>
<section id="vpn" class="level2">
<h2 class="anchored" data-anchor-id="vpn">VPN</h2>
<p>Mein Wireguard-VPN soll unter den Netzen <code>10.3.3.0/24</code> und <code>fd04:bab0:3::/64</code> laufen. Alle Clients sollen sich gegenseitig sehen und anpingen können. Auf Wunsch soll der gesamte Traffic über das VPN geroutet werden.</p>
</section>
<section id="installation" class="level2">
<h2 class="anchored" data-anchor-id="installation">Installation</h2>
<p>Unter Ubuntu lässt sich Wireguard auf Server und Clients wie folgt installieren:</p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#Ubuntu</span></span>
<span id="cb1-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">apt</span> install wireguard</span>
<span id="cb1-3"> </span>
<span id="cb1-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#Arch, btw</span></span>
<span id="cb1-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">pacman</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-S</span> wireguard-tools</span></code></pre></div>
</section>
<section id="schlüssel-erzeugen" class="level2">
<h2 class="anchored" data-anchor-id="schlüssel-erzeugen">Schlüssel erzeugen</h2>
<p>Auf meiner Zertifikationsinstanz (oder auf jedem anderen Rechner) erstelle ich mir einen neuen Ordner und erzeuge für den Server sowie für jeden Client ein Paar aus privatem und öffentlichem Schlüssel.</p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> bash</span>
<span id="cb2-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">umask</span> 077 <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&amp;&amp;</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">wg</span> genkey <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tee</span> server-private.key <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">wg</span> pubkey <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> server-public.key</span>
<span id="cb2-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">umask</span> 077 <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&amp;&amp;</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">wg</span> genkey <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tee</span> client1-private.key <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">wg</span> pubkey <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> client1-public.key</span>
<span id="cb2-4"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">umask</span> 077 <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&amp;&amp;</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">wg</span> genkey <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tee</span> client2-private.key <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">wg</span> pubkey <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> client2-public.key</span>
<span id="cb2-5"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">umask</span> 077 <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&amp;&amp;</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">wg</span> genkey <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tee</span> client3-private.key <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">wg</span> pubkey <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> client3-public.key</span></code></pre></div>
<p>Die Inhalte der Schlüsseldateien werden gleich plaintext in die Configdateien geschrieben.</p>
</section>
<section id="server-aufsetzen" class="level2">
<h2 class="anchored" data-anchor-id="server-aufsetzen">Server aufsetzen</h2>
<p>Nach der Installation existiert das Verzeichnis <code>/etc/wireguard</code>. In diesem Verzeichnis liegen die <code>.conf</code>-Dateien der VPNs, egal ob Server oder Client. Der Name der <code>.conf</code>-Datei entscheidet über den Namen der Interfaceschnittstelle. Benenne ich die Datei foobar.conf, so wird ein Tunneldevice mit dem Namen <code>foobar</code> erzeugt. Die Datei <code>tun0.conf</code> erzeugt ein Interface mit dem Namen <code>tun0</code>. Standardmäßig (also in den Manuals im Netz) werden für Wireguard <code>wg0</code>-Interfaces erzeugt.</p>
<p>Wir erzeugen also die Datei <code>wg0.conf</code> und geben ihr folgenden Inhalt:</p>
<div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb3-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ---------- Server Config ----------</span></span>
<span id="cb3-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">[Interface]</span></span>
<span id="cb3-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">## welche IP4-Adresse hat der Server im Tunnel?</span></span>
<span id="cb3-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Address</span> = 10.3.3.1/24</span>
<span id="cb3-5"></span>
<span id="cb3-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">## welche IPv6-Adresse hat der Server im Tunnel?</span></span>
<span id="cb3-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Address</span> = fd04:bab0:3::1/64 </span>
<span id="cb3-8"></span>
<span id="cb3-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Wenn ihr iptables nutzt, dann wird hier das NAT zum Internet klargemacht</span></span>
<span id="cb3-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Mein Device heisst eth0, eures auch? ansonsten ändern!</span></span>
<span id="cb3-11"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">PostUp</span> = iptables <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-A</span> FORWARD <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-i</span> wg0 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-j</span> ACCEPT<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">;</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">iptables</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-t</span> nat <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-A</span> POSTROUTING <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-s</span> 10.3.3.0/24 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> eth0 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-j</span> MASQUERADE<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">;</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ip6tables</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-A</span> FORWARD <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-i</span> wg0 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-j</span> ACCEPT<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">;</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ip6tables</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-t</span> nat <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-A</span> POSTROUTING <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-s</span> fd04:bab0:3::/64 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> eth0 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-j</span> MASQUERADE </span>
<span id="cb3-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Sobald der VPN beendet wird, werden die iptables Regeln rückgängig gemacht</span></span>
<span id="cb3-13"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">PostDown</span> = iptables <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-D</span> FORWARD <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-i</span> wg0 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-j</span> ACCEPT<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">;</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">iptables</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-t</span> nat <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-D</span> POSTROUTING <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-s</span> 10.3.3.0/24 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> eth0 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-j</span> MASQUERADE<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">;</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ip6tables</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-D</span> FORWARD <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-i</span> wg0 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-j</span> ACCEPT<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">;</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ip6tables</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-t</span> nat <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-D</span> POSTROUTING <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-s</span> fd04:bab0:3::/64 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> eth0 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-j</span> MASQUERADE</span>
<span id="cb3-14"></span>
<span id="cb3-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Hier kommt der private Key des Servers hin, in Plaintext</span></span>
<span id="cb3-16"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">PrivateKey</span> = OHUJätschibätschifasfdeg92wz4CvFqlWWUW74dfgM5+zPfuEU=</span>
<span id="cb3-17"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Auf welchem Port soll der Server lauschen?</span></span>
<span id="cb3-18"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Diesen Port in der Firewall freigeben!</span></span>
<span id="cb3-19"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ListenPort</span> = 45881 </span>
<span id="cb3-20"></span>
<span id="cb3-21"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">## Für jeden Client kommt hier eine eigene Identifikation</span></span>
<span id="cb3-22"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">[Peer]</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Client1</span></span>
<span id="cb3-23"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Schreibe hier den öffentlichen Schlüssel des Client1 hinein</span></span>
<span id="cb3-24"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">PublicKey</span> = AfuckAfDfejoqfooobaaarmHILbtoxReB6ZjzNuMtyYNxlM= </span>
<span id="cb3-25"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Mit welchen IP4 und IPv6-Adressen soll sich der Client verbinden?</span></span>
<span id="cb3-26"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Hier müssen ein /32  und /128 verwendet werden (= genau 1 IP-Adresse erlaubt)</span></span>
<span id="cb3-27"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">AllowedIPs</span> = 10.3.3.2/32, fd04:bab0:3::2/128 </span>
<span id="cb3-28"></span>
<span id="cb3-29"></span>
<span id="cb3-30"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Hier wiederholt sich das Ganze für Client2</span></span>
<span id="cb3-31"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">[Peer]</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># CLient2</span></span>
<span id="cb3-32"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Client public key</span></span>
<span id="cb3-33"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">PublicKey</span> = 1xejE9Z2OnkqkuckuckFcOsoLA623M1yRr+7/v7SmAtP36UmG8=  </span>
<span id="cb3-34"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># IPs client can connect as (IPv4 /32  and IPv6 /128)</span></span>
<span id="cb3-35"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">AllowedIPs</span> = 10.3.3.3/32, fd04:bab0:3::3/128 </span>
<span id="cb3-36"></span>
<span id="cb3-37"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">[Peer]</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Client3</span></span>
<span id="cb3-38"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Client public key</span></span>
<span id="cb3-39"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">PublicKey</span> = sCid523sdfXwQHoErOyXyIk8UNEz36aff7+R9MIU8Xm4wc=  </span>
<span id="cb3-40"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># IPs client can connect as (IPv4 /32  and IPv6 /128)</span></span>
<span id="cb3-41"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">AllowedIPs</span> = 10.3.3.4/32, fd04:bab0:3::4/128 </span></code></pre></div>
<ul>
<li>Der Server lauscht unter IP4 und IPv6 auf Port <code>45881</code>. Ihr könnt auch irgendeinen anderen Port auswählen.</li>
<li>Der Server wird unter den Adressen <code>10.3.3.1/24</code> und <code>fd04:bab0:3::1/64</code> über den Tunnel ereichbar sein. Ebenso haben derzeit 3 Clients Zugriff, wobei jeder Client eine fixe IP4 und IPv6 im Tunnelnetz erhält.</li>
<li>Bei den <code>AllowedIPs</code> ist euch sicherlich aufgefallen, dass bei IP4 ein <code>/32</code> und bei IPv6 ein <code>/128</code> hinter die Adresse geschrieben werden muss.
<ul>
<li>Auf dem Server fungiert <code>AllowedIPs</code> ähnlich wie ein Router und gibt an, wohin der Datenverkehr geroutet werden soll. Daher genügt die Angabe von <code>/32</code> oder eben <code>/128</code> (genau eine IP-Adresse).</li>
<li>In der gleich folgenden Client-Config fungiert <code>AllowedIPs</code> wie eine Access-Controll-List. Daher muss in der Client-Config ein <code>/24</code> bzw. <code>/64</code> definiert werden, um alles von <code>10.3.3.*</code> bzw. <code>fd04:bab0:3::</code> zu akzeptieren.</li>
</ul></li>
<li>Soll ein weiterer Client hinzugefügt werden, muss in der Server-Config ein neuer [Peer]-Block mit dem puplic key des neuen Clients hinzugefügt werden.</li>
</ul>
<section id="server-starten" class="level3">
<h3 class="anchored" data-anchor-id="server-starten">Server starten</h3>
<p>Ähnlich wie bei openVPN liest systemd das Verzeichnis <code>/etc/wireguard</code> aus und macht alle dort befindlichen <code>MY-VPN.conf</code>-Dateien verfügbar über den Service <code>wg-quick@MY-VPN.service</code>.</p>
<p>Wir können unseren <code>wg0</code>-Server starten mittels:</p>
<div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb4-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Starten</span></span>
<span id="cb4-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">systemctl</span> start wg-quick@wg0.service</span>
<span id="cb4-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Logs ansehen</span></span>
<span id="cb4-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">journalctl</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-u</span> wg-quick@wg0.service <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-f</span></span></code></pre></div>
</section>
</section>
<section id="firewall-anpassen" class="level2">
<h2 class="anchored" data-anchor-id="firewall-anpassen">Firewall anpassen</h2>
<p>Falls ihr eine Firewall benutzt (und ich hoffe doch sehr, dass dies der Fall ist), muss diese für Wireguard angepasst werden. Einerseits muss der Server-Port freigegeben werden (ich habe da ja <code>45881</code>), anderseits müssen wir intern <code>NAT</code> einrichten, wenn der Internetverkehr über den Tunnel geroutet werden soll.</p>
<section id="iptables" class="level3">
<h3 class="anchored" data-anchor-id="iptables">iptables</h3>
<p>Die iptables-Firewall muss auf dem Server und auf den Clients angepasst werden, damit openVPN funktioniert:</p>
<div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb5-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">## Akzeptiere Pakete von den wg+ Interfaces</span></span>
<span id="cb5-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">iptables</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-A</span> INPUT <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-i</span> wg+ <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-j</span> ACCEPT</span>
<span id="cb5-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">iptables</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-A</span> FORWARD <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-i</span> wg+ <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-j</span> ACCEPT</span>
<span id="cb5-4"></span>
<span id="cb5-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">## auf dem Server muss Port 45881 tcp/udp geöffnet werden</span></span>
<span id="cb5-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">iptables</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-A</span> INPUT <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-i</span> eth0 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-p</span> tcp <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--dport</span> 45881 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-j</span> ACCEPT</span>
<span id="cb5-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">iptables</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-A</span> INPUT <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-i</span> eth0 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-p</span> udp <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--dport</span> 45881 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-j</span> ACCEPT</span></code></pre></div>
<p>Wenn euer Device nicht <code>eth0</code> heisst, müsst ihr den Befehl entsprechend anpassen.</p>
</section>
<section id="ufw" class="level3">
<h3 class="anchored" data-anchor-id="ufw">ufw</h3>
<p>Die ufw-Firewall muss auf dem Server angepasst werden, damit Wireguard funktioniert. Zunächst muss der Serverport freigegeben werden:</p>
<div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb6-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> ufw allow 45881</span></code></pre></div>
<p>Anschließend müssen drei weitere Dateien editiert werden, damit das Netz funktioniert.</p>
<ol type="1">
<li><code>/etc/default/ufw</code></li>
</ol>
<div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb7-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nano</span> /etc/default/ufw </span>
<span id="cb7-2"></span>
<span id="cb7-3"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">DEFAULT_FORWARD_POLICY</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ACCEPT"</span></span></code></pre></div>
<p>2a. <code>/etc/ufw/before.rules</code>, füge die folgenden Zeilen <strong>vor</strong> der <code>*filter</code>-Sektion ein, um das <code>NAT</code> für IPv4 zu aktivieren:</p>
<div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb8-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nano</span> /etc/ufw/before.rules</span>
<span id="cb8-2"></span>
<span id="cb8-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># NAT-Tabelle hinzufügen</span></span>
<span id="cb8-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">*nat</span></span>
<span id="cb8-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:POSTROUTING</span> ACCEPT <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">[</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">0:0</span><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">]</span></span>
<span id="cb8-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># OpenVPN-Regeln hinzufügen</span></span>
<span id="cb8-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">-A</span> POSTROUTING <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-s</span> 10.3.3.0/24 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> eth0 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-j</span> MASQUERADE</span>
<span id="cb8-8"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">COMMIT</span></span></code></pre></div>
<p>2b. <code>/etc/ufw/before6.rules</code>, füge die folgenden Zeilen <strong>vor</strong> der <code>*filter</code>-Sektion ein, um das <code>NAT</code> für IPv6 zu aktivieren:</p>
<div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb9-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nano</span> /etc/ufw/before6.rules</span>
<span id="cb9-2"></span>
<span id="cb9-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># NAT-Tabelle hinzufügen</span></span>
<span id="cb9-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">*nat</span></span>
<span id="cb9-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:POSTROUTING</span> ACCEPT <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">[</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">0:0</span><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">]</span></span>
<span id="cb9-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># OpenVPN-Regeln hinzufügen</span></span>
<span id="cb9-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">-A</span> POSTROUTING <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-s</span> fd04:bab0:3::/64 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> eth0 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-j</span> MASQUERADE</span>
<span id="cb9-8"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">COMMIT</span></span></code></pre></div>
<p>Wenn euer Device nicht <code>eth0</code> heisst, müsst ihr den Befehl entsprechend anpassen. Und falls ihr diese Einstellung gerade getroffen habt, könnt ihr in der <code>wg0.conf</code> des Servers die Parameter <code>PostUp</code> und <code>PostUp</code> wieder auskommentieren.</p>
<ol start="3" type="1">
<li><code>/etc/ufw/sysctl.conf</code></li>
</ol>
<div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb10-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nano</span> /etc/ufw/sysctl.conf</span>
<span id="cb10-2"></span>
<span id="cb10-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">net/ipv4/ip_forward=1</span></span>
<span id="cb10-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">net/ipv6/conf/default/forwarding=1</span></span>
<span id="cb10-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">net/ipv6/conf/all/forwarding=1</span></span></code></pre></div>
</section>
</section>
<section id="client-einrichten" class="level2">
<h2 class="anchored" data-anchor-id="client-einrichten">Client einrichten</h2>
<p>Auf den Clients erzeugen wir ebenfalls die Datei <code>/etc/wireguard/wg0.conf</code> und geben ihr diesen Inhalt:</p>
<div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb11-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># -------- Client Config ------------------</span></span>
<span id="cb11-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">[Interface]</span></span>
<span id="cb11-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># IP4 Adresse des Clients, so wie in der Server-Config angegeben (/32!)</span></span>
<span id="cb11-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Dieser Client bekommt 10.3.3.2</span></span>
<span id="cb11-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Address</span> = 10.3.3.2/32 </span>
<span id="cb11-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># IPv6 Adresse des Clients (use /128!)</span></span>
<span id="cb11-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Dieser Client bekommt fd04:bab0:3::2</span></span>
<span id="cb11-8"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Address</span> = fd04:bab0:3::2/128 </span>
<span id="cb11-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Der Private Key von Client1 im Plaintext</span></span>
<span id="cb11-10"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">PrivateKey</span> = GNJJAJT0MQnxRHga8Rzp/hLGoCtsefljhelahDks6EMD8Vw= </span>
<span id="cb11-11"></span>
<span id="cb11-12"></span>
<span id="cb11-13"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">[Peer]</span></span>
<span id="cb11-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Wie ist der Server erreichbar? Adresse und Port</span></span>
<span id="cb11-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#Endpoint = [2a02:08:15:4500:fckafd:4]:45881</span></span>
<span id="cb11-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#Endpoint = 192.168.0.1:45881</span></span>
<span id="cb11-17"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Endpoint</span> = vpn.myserver.org:45881</span>
<span id="cb11-18"></span>
<span id="cb11-19"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Der öffentliche Schlüssel des Servers im Plaintext</span></span>
<span id="cb11-20"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">PublicKey</span> = emV/wFCKAFD4WIyakB/JEi7jp9wH7zBCi81W+qjuMkWc= </span>
<span id="cb11-21"></span>
<span id="cb11-22"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Sende alle x Sekunden einen Ping an das Netz </span></span>
<span id="cb11-23"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># um den Tunnel aufrecht zu erhalten. </span></span>
<span id="cb11-24"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Sollte NIE auf dem Server gesetzt werden, </span></span>
<span id="cb11-25"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># sondern nur dort, wo auch "Endpoint" definiert ist. </span></span>
<span id="cb11-26"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Also hier im Client...</span></span>
<span id="cb11-27"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">PersistentKeepalive</span> = 5</span>
<span id="cb11-28"></span>
<span id="cb11-29"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Was soll durch den Tunnel geroutet werden?</span></span>
<span id="cb11-30"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">## Option 1: nur Tunnelkrams durch den Tunnel routen</span></span>
<span id="cb11-31"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">AllowedIPs</span> = 10.3.3.0/24, fd04:3::/64 </span>
<span id="cb11-32"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">## Option 2: ALLES durch den Tunnel routen</span></span>
<span id="cb11-33"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#AllowedIPs = 0.0.0.0/0, ::/0 </span></span></code></pre></div>
<ul>
<li>Diese Datei muss ich nun bei jedem Client nach dem selben Muster anlegen.</li>
<li>Der Client erhält seine fest IP4 und IPv6 über den Tunnel</li>
<li>Dieses Mal müssen unter <code>Address</code> jeweils ein <code>/32</code> bzw <code>/128</code> vergeben werden (= 1 IP Adresse).
<ul>
<li>Der Parameter <code>AllowedIPs</code> fungiert im Clientmodus wie eine Access-Controll-List. Daher wird an dieser Stelle wieder ein <code>/24</code> bzw. <code>/64</code> definiert, um alles von <code>10.3.3.*</code> bzw. <code>fd04:bab0:3::</code> über den Tunnel zu routen.</li>
</ul></li>
<li>Soll der gesamte Datenverkehr über den VPN-Tunnel geroutet werden, muss die zweite <code>AllowedIPs</code>-Zeile aktiviert (und die darüberstehende auskommentiert) werden.</li>
</ul>
</section>
<section id="android" class="level2">
<h2 class="anchored" data-anchor-id="android">Android</h2>
<p>Für mein Handy erstelle mich mir wie oben beschrieben ein Schlüsselpaar und generiere mir eine Clientconfig wie oben, wobei ich die zweite <code>AllowedIPs</code>-Option wähle (alles übers VPN routen). Diese <code>wg0.conf</code> übertrage ich per KDE Connect auf mein Handy.</p>
<p>Als App installiere ich mittels F-Droid <a href="https://f-droid.org/packages/com.zaneschepke.wireguardautotunnel/">WG Tunnel</a> von <a href="https://github.com/zaneschepke/wgtunnel">Zane Schepke</a>, da die Original-Wireguard-App Ende 2023 aus dem F-Droid-Repository geflogen ist (weil sie einen integrierten Aktualisierer bekommen hat, der standardmäßig aktiviert ist und nicht transparent angibt, von wo aus er Aktualisierungen herunterlädt; noch fragt er um Zustimmung).</p>
<p>Jetzt kann ich einfach die übertragene <code>wg0.conf</code>-Datei in der App importieren, und alles funktioniert bestens. Ok, in den App-Einstellungen musste ich noch “Tunnel on untrusted wifi” und “Tunnel on mobile data” aktivieren, dann hat es aber sofort funktioniert.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.produnis.de/blog/posts/2024-03-22-wireguard/settings_screen.webp" class="img-fluid figure-img" width="300"></p>
<figcaption>“Tunnel on untrusted wifi” und “Tunnel on mobile data” aktivieren</figcaption>
</figure>
</div>
</section>
<section id="weblinks" class="level2">
<h2 class="anchored" data-anchor-id="weblinks">Weblinks</h2>
<ul>
<li><a href="https://www.wireguard.com/" class="uri">https://www.wireguard.com/</a></li>
<li><a href="https://www.timoschindler.de/tag/arch-linux/" class="uri">https://www.timoschindler.de/tag/arch-linux/</a></li>
<li><a href="https://github.com/zaneschepke/wgtunnel" class="uri">https://github.com/zaneschepke/wgtunnel</a></li>
<li><a href="https://git.zilium.de/-/snippets/8" class="uri">https://git.zilium.de/-/snippets/8</a></li>
<li><a href="https://android.stackexchange.com/questions/254262/why-isnt-wireguard-available-on-f-droid" class="uri">https://android.stackexchange.com/questions/254262/why-isnt-wireguard-available-on-f-droid</a></li>
<li><a href="https://requestforcomments.de/archives/682" class="uri">https://requestforcomments.de/archives/682</a></li>
</ul>
            <br><center>
            <div class="matrixfoot" id="matrixfooter">
            <a href="https://matrix.to/#/#produnis-blog:tchncs.de">
            <img src="https://www.produnis.de/images/Matrix.webp" width="60">
            </a>
            Diskussion per Matrix unter <a href="https://matrix.to/#/#produnis-blog:tchncs.de">https://matrix.to/#/#produnis-blog:tchncs.de</a>
            </div>
            </center><br>&nbsp;
        


</section>

 ]]></description>
  <category>wireguard</category>
  <category>Heimserver</category>
  <category>IPv6</category>
  <category>ubuntuusers</category>
  <guid>https://www.produnis.de/blog/posts/2024-03-22-wireguard/</guid>
  <pubDate>Fri, 22 Mar 2024 22:24:00 GMT</pubDate>
  <media:content url="https://www.produnis.de/blog/posts/2024-03-22-wireguard/wireguard.webp" medium="image" type="image/webp"/>
</item>
<item>
  <title>Android-Geräte dem VPN hinzufügen und IPv6</title>
  <dc:creator>Joe Slam</dc:creator>
  <link>https://www.produnis.de/blog/posts/2024-03-19-openvpn-android/</link>
  <description><![CDATA[ 





<p>Im <a href="../2024-03-16-openvpn/">letzten Blogpost</a> habe ich beschrieben, wie ich mein privates Netz mit openVPN aufbaue. In diesem Post möchte ich zeigen, wie man Android-Geräte dem Netz hinzufügen kann, und was ich tun musste, damit der Server korrekt auf IPv4 und IPv6-Anfragen lauscht.</p>
<section id="sec-ipv6" class="level2">
<h2 class="anchored" data-anchor-id="sec-ipv6">IPv6</h2>
<p>Mein Heimserver, der die VPNs aufbaut, ist sowohl per IPv4 als auch per IPv6 erreichbar. Da das Mobilnetz an Handy und Tablet fast ausschließlich IPv6 nutzt, ist es eine gute Idee, auf beiden Netzen zu lauschen. Damit der openVPN-Server sowohl per IPv4 als auch per IPv6 auf Anfragen antwortet, ändere ich in der Server-Config die Stelle</p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">proto</span> udp</span></code></pre></div>
<p>auf</p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">proto</span> udp6</span></code></pre></div>
<section id="udp6-antwortet-mit-anderer-adresse" class="level3">
<h3 class="anchored" data-anchor-id="udp6-antwortet-mit-anderer-adresse">UDP6 antwortet mit anderer Adresse</h3>
<p>Bei mir gab es das Problem, dass <code>udp6</code> nicht mit der IP-Adresse auf Anfragen antwortet, an welche die Anfrage abgeschickt wurde. Mein Server hat beispielsweise die feste IPv6 <code>2002:bla:fasel::4/64</code>. Mein Handy sendet nun aus dem Mobilnetz (da gibt es <strong>nur</strong> IPv6) an diese Adresse seine Anfrage, aber der Server antwortet mit einer neuen IPv6, z.B. <code>2002:bla:fasel:ätschi:bätsch:4/64</code>. In diesem Falle kommt keine Verbindung zu Stande (das scheint <a href="https://community.openvpn.net/openvpn/ticket/442">schon länger und immer wieder ein Problem mit UDP zu sein</a>).</p>
<p>Die Lösung besteht darin, in der Server-Config die Zeile <code>multihome</code> zu ergänzen.</p>
<div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb3-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">proto</span> udp6</span>
<span id="cb3-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">multihome</span></span></code></pre></div>
<p>Die Option stellt sicher, dass die UDP-Antwortpakete immer von der Adresse gesendet werden, an welche der Client seine Anfragen gestellt hat.</p>
</section>
<section id="ipv6-ula-einrichten." class="level3">
<h3 class="anchored" data-anchor-id="ipv6-ula-einrichten.">IPv6-ULA einrichten.</h3>
<p>Bislang bekommen alle Clients eine IP4 aus dem 10.5.5.0/24 Bereich, wobei ich über das <code>ccd</code>-Verzeichnis jedem Client eine feste IP gegeben habe. Da ich den Server nun auch aus dem IPv6-Netz heraus erreichbar gemacht habe, verteile ich über mein VPN zusätzlich IPv6-ULA-Adressen aus dem Bereich <code>fd04:bab0::/64</code>, so dass alle Clients auch per IPv6 ansprechbar sind.</p>
<p>Hierfür ergänze ich die Server-Config um folgende Zeilen:</p>
<div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb4-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">server-ipv6</span> fd04:bab0::/64        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ULA IPv6 Subnetz für OpenVPN-Clients</span></span>
<span id="cb4-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">push</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"route-ipv6 fd04:bab0::/64"</span>  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ULA IPv6 Subnetz an die Clients weitergeben</span></span></code></pre></div>
<p>Ebenfalls ergänze ich im <code>ccd</code>-Verzeichnis die Dateien aller Clients um folgende Zeile:</p>
<div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb5-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ifconfig-ipv6-push</span> fd04:bab0::xyz/64</span></code></pre></div>
<p>wobei ich für <code>xyz</code> jeweils die selbe Ziffer nehme wie im IPv4 Netz.</p>
<p>Nach einem Neustart des VPN-Servers erhalten alle Clients automatisch eine <code>10.5.5.0/24</code> sowie eine <code>fd04:bab0::/64</code>-Adresse und können sich gegenseitig über IPv4 oder IPv6 anpingen. An den Client-Configs muss nichts geändert werden.</p>
</section>
</section>
<section id="ipv6-internet-durch-den-tunnel-routen" class="level2">
<h2 class="anchored" data-anchor-id="ipv6-internet-durch-den-tunnel-routen">IPv6 Internet durch den Tunnel routen</h2>
<p>Damit auch das globale IPv6-Internet durch den Tunnel geroutet werden kann, müssen die Firewallregeln angepasst werden.</p>
<section id="iptables" class="level3">
<h3 class="anchored" data-anchor-id="iptables">iptables</h3>
<div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb6-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># iptables</span></span>
<span id="cb6-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ip6tables</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-t</span> nat <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-D</span> POSTROUTING <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-s</span> fd04:bab0::/64 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> eth0 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-j</span> MASQUERADE</span></code></pre></div>
</section>
<section id="ufw" class="level3">
<h3 class="anchored" data-anchor-id="ufw">ufw</h3>
<p>Für IPv6 muss die Datei <code>/etc/ufw/before6.rules</code> angepasst werden. Füge die folgenden Zeilen <strong>vor</strong> der <code>*filter</code>-Sektion ein, um das <code>NAT</code> für IPv6 zu aktivieren:</p>
<div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb7-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nano</span> /etc/ufw/before6.rules</span>
<span id="cb7-2"></span>
<span id="cb7-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># NAT-Tabelle hinzufügen</span></span>
<span id="cb7-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">*nat</span></span>
<span id="cb7-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:POSTROUTING</span> ACCEPT <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">[</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">0:0</span><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">]</span></span>
<span id="cb7-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># OpenVPN-Regeln hinzufügen</span></span>
<span id="cb7-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">-A</span> POSTROUTING <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-s</span> fd04:bab0::/64 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> eth0 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-j</span> MASQUERADE</span>
<span id="cb7-8"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">COMMIT</span></span></code></pre></div>
</section>
</section>
<section id="zertifikate-erstellen" class="level2">
<h2 class="anchored" data-anchor-id="zertifikate-erstellen">Zertifikate erstellen</h2>
<p>Damit Handy und Tablet das VPN nutzen können, benötigen sie wieder gültige Zertifikate und den <code>ta.key</code> des VPNs (siehe <a href="../2024-03-16-openvpn/">letzter Blogpost</a>).</p>
<p>Dazu wechsle ich auf meine Zertifikationsinstanz und erstelle wie gewohnt Zertifiakte für Handy und Tablet, z.B. so:</p>
<div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb8-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> bash</span>
<span id="cb8-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">cd</span> /etc/easy-rsa</span>
<span id="cb8-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">easyrsa</span> gen-req handy nopass</span>
<span id="cb8-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">easyrsa</span> sign-req client handy</span>
<span id="cb8-5"></span>
<span id="cb8-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">easyrsa</span> gen-req tablet nopass</span>
<span id="cb8-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">easyrsa</span> sign-req client tablet</span></code></pre></div>
<section id="zertifikat-für-android-umwandeln" class="level3">
<h3 class="anchored" data-anchor-id="zertifikat-für-android-umwandeln">Zertifikat für Android umwandeln</h3>
<p>Wir können Androids Zertifikateverwaltung nutzen, um die Zertifikate halbwegs “sicher” auf den Geräten zu verwalten. Hierfür bündeln wir</p>
<ul>
<li><code>/etc/easy-rsa/pki/private/handy.key</code></li>
<li><code>/etc/easy-rsa/pki/issued/handy.crt</code></li>
<li><code>/etc/easy-rsa/pki/ca.crt</code></li>
</ul>
<p>in einer PKCS-Datei mit dem Namen <code>handy.p12</code>, die wir dann später am Handy importieren können. Der dazugeöhrige Befehl lautet:</p>
<div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb9-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">openssl</span> pkcs12 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-export</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-in</span> CERT <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-inkey</span> KEY <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-certfile</span> CA <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-name</span> CLIENTNAME <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-out</span> OUTPUT.p12</span></code></pre></div>
<p>In meinem Fall also</p>
<div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb10-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">openssl</span> pkcs12 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-export</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-in</span> pki/issued/handy.crt <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-inkey</span> pki/private/handy.key <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-certfile</span> pki/ca.crt <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-name</span> handy <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-out</span> handy.p12</span></code></pre></div>
<p>Ihr werdet nach einem Export-Passwort gefragt. Denkt euch irgendetwas halbwegs sicheres aus. Am Handy muss später dieses Passwort beim Import eingegeben werden.</p>
<p>Die erzeugte PKCS-Datei <code>handy.p12</code> sowie der <code>ta.key</code> des VPN müssen nun auf das Handy kopiert werden. Ich nutze hierfür meine Nextcloud, KDE Connect oder eine E-Mail an mich selbst.</p>
<ul>
<li>Ist die Datei <code>handy.p12</code> auf das Handy kopiert, klicke ich am Handy auf eben diese Datei, um die Zertifikate in den Android-Zertifikatespeicher aufzunehmen. Hierbei muss das oben erwähnte Passwort eingegeben werden.</li>
<li>Die Datei <code>ta.key</code> kopiere ich an eine Stelle meines Handys, die ich mir merken kann, z.B. “Dokumente/OpenVPN”</li>
</ul>
</section>
</section>
<section id="openvpn-for-android" class="level2">
<h2 class="anchored" data-anchor-id="openvpn-for-android">openVPN for Android</h2>
<p>Für Android steht z.B. über F-Droid das Paket von <a href="https://github.com/schwabe/ics-openvpn">blinkt</a> zur Verfügung, siehe <a href="https://f-droid.org/packages/de.blinkt.openvpn/" class="uri">https://f-droid.org/packages/de.blinkt.openvpn/</a></p>
<ul>
<li>In der Client-App erstelle ich ein neues Profil mit dem Namen “test” (Name ist ja egal).</li>
<li>Im Reiter “Basic” klicke ich bei “Client Certificate” auf den Select-Button. So kann ich das eben in Android importierte Zertifikat auswählen.</li>
</ul>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.produnis.de/blog/posts/2024-03-19-openvpn-android/androidvpn01.webp" class="img-fluid figure-img" width="300"></p>
<figcaption>importierte Zertifikate im Androidspeicher</figcaption>
</figure>
</div>
<ul>
<li>Im Reiter “Server List” trage ich meinen Server ein und wähle unter “Protocol” <code>UDP</code>.</li>
</ul>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.produnis.de/blog/posts/2024-03-19-openvpn-android/androidvpn02udp.webp" class="img-fluid figure-img" width="300"></p>
<figcaption>Serveradresse und Protocol “UDP”</figcaption>
</figure>
</div>
<ul>
<li>Unter dem Reiter “Authentication/Encryption” müssen folgende Einstellungen getroffen werden:
<ul>
<li>bei TLS-Settings entferne ich den Haken bei “Certificate Hostname Check”</li>
</ul></li>
</ul>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.produnis.de/blog/posts/2024-03-19-openvpn-android/androidvpn03.webp" class="img-fluid figure-img" width="300"></p>
<figcaption>kein “Certificate Hostname Check”</figcaption>
</figure>
</div>
<ul>
<li>dafür setze ich den Haken bei “Use Control Channel Authentication/Encryption”
<ul>
<li>als “TLS Auth/TLS Encrpytion File” wähle ich den auf das Handy kopierten <code>ta.key</code></li>
<li>als “Authentication/encryption method” wähle ich <code>Encryption (--tls-crypt)</code></li>
</ul></li>
</ul>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.produnis.de/blog/posts/2024-03-19-openvpn-android/androidvpn04.webp" class="img-fluid figure-img" width="300"></p>
<figcaption>TLS Auth/TLS Encrpytion File ist <code>ta.key</code> und Encryption <code>--tls-crypt</code></figcaption>
</figure>
</div>
<ul>
<li>bei “Encryption ciphers” trage ich (gemäß meiner Server-Config) <code>AES-256-CBC:AES-256-GCM</code> ein.</li>
</ul>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.produnis.de/blog/posts/2024-03-19-openvpn-android/androidvpn05.webp" class="img-fluid figure-img" width="300"></p>
<figcaption>Encryption ciphers auf <code>AES-256-CBC:AES-256-GCM</code></figcaption>
</figure>
</div>
<p>Das funktioniert wunderbar, und mein Handy kann sich mit meinem VPN verbinden.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.produnis.de/blog/posts/2024-03-19-openvpn-android/androidvpn06.webp" class="img-fluid figure-img" width="300"></p>
<figcaption>erfolgreich verbunden</figcaption>
</figure>
</div>
<p>Jetzt können sich alle Clients (auch die Mobilgeräte über IPv6) mit dem Server verbinden und sich gegenseitig anpingen.</p>
<section id="gesamten-verkehr-der-mobilgeräte-über-das-vpn-routen" class="level3">
<h3 class="anchored" data-anchor-id="gesamten-verkehr-der-mobilgeräte-über-das-vpn-routen">gesamten Verkehr der Mobilgeräte über das VPN routen</h3>
<p>Im Reiter “Routing” können bei Bedarf die Haken bei “Use default Route” für IPv4 und IPv6 gesetzt werden. Dann wird der gesamte Datenverkehr des Handys über das VPN geroutet. Die Server-Config muss dafür nicht angefasst werden.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.produnis.de/blog/posts/2024-03-19-openvpn-android/androidvpn07.webp" class="img-fluid figure-img" width="300"></p>
<figcaption>alles übers VPN routen</figcaption>
</figure>
</div>
<p>Das ist sehr vorteilhaft, z.B. wenn man in einem ranzigen WLAN unterwegs ist (McDoof, Bahn, etc.) oder im Ausland dennoch “Sportschau” übers Netz schauen möchte. Auch funktioniert KDE Connect bestens über das VPN, was für meinen Büro-PC sehr gut ist.</p>
<p>Möchtet ihr auch bei anderen Clients (z.B. beim Laptop) den gesamten Datenverkehr durch das VPN routen, müsst ihr in dessen Client-Config folgende Zeile ergänzen:</p>
<div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb11-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">redirect-gateway</span> def1 <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># leitet gesamten Datenverkehr über das VPN</span></span></code></pre></div>
<p>Das <code>def1</code> steht für “default route” und muss nicht weiter angepasst werden. Nun läuft auch am Laptop alles über das VPN.</p>
</section>
</section>
<section id="weblinks" class="level2">
<h2 class="anchored" data-anchor-id="weblinks">Weblinks</h2>
<ul>
<li><a href="https://wiki.archlinux.org/title/OpenVPN" class="uri">https://wiki.archlinux.org/title/OpenVPN</a></li>
<li><a href="https://f-droid.org/packages/de.blinkt.openvpn/" class="uri">https://f-droid.org/packages/de.blinkt.openvpn/</a></li>
<li><a href="https://github.com/schwabe/ics-openvpn" class="uri">https://github.com/schwabe/ics-openvpn</a></li>
<li><a href="https://community.openvpn.net/openvpn/ticket/442" class="uri">https://community.openvpn.net/openvpn/ticket/442</a></li>
<li><a href="https://requestforcomments.de/archives/682" class="uri">https://requestforcomments.de/archives/682</a></li>
</ul>
            <br><center>
            <div class="matrixfoot" id="matrixfooter">
            <a href="https://matrix.to/#/#produnis-blog:tchncs.de">
            <img src="https://www.produnis.de/images/Matrix.webp" width="60">
            </a>
            Diskussion per Matrix unter <a href="https://matrix.to/#/#produnis-blog:tchncs.de">https://matrix.to/#/#produnis-blog:tchncs.de</a>
            </div>
            </center><br>&nbsp;
        


</section>

 ]]></description>
  <category>openvpn</category>
  <category>Heimserver</category>
  <category>IPv6</category>
  <category>ubuntuusers</category>
  <guid>https://www.produnis.de/blog/posts/2024-03-19-openvpn-android/</guid>
  <pubDate>Tue, 19 Mar 2024 08:24:00 GMT</pubDate>
  <media:content url="https://www.produnis.de/blog/posts/2024-03-19-openvpn-android/openvpnlogo.webp" medium="image" type="image/webp"/>
</item>
<item>
  <title>Ein privates Netz mit openVPN erstellen</title>
  <dc:creator>Joe Slam</dc:creator>
  <link>https://www.produnis.de/blog/posts/2024-03-16-openvpn/</link>
  <description><![CDATA[ 





<p>In diesem Blogpost zeige ich Schritt für Schritt, wie ich mein privates openVPN-Netzwerk aufgebaut habe. Zu dem Thema gibt es übrigens eine sehr empfehlenswerte Podcastfolge von <a href="https://requestforcomments.de/archives/682">Request for Comments</a>, in welcher Clemens Schrimpe ausführlich über VPN spricht.</p>
<p>Mein VPN soll die IPs <code>10.5.5.0/24</code> verwenden und eigentlich “nur” dazu dienen, die Clients miteinander zu verbinden. Es kann aber auch easy der gesamte Internettraffic über dass VPN geleitet werden.</p>
<section id="hardware" class="level2">
<h2 class="anchored" data-anchor-id="hardware">Hardware</h2>
<p>Folgende Geräte kommen zum Einsatz:</p>
<ul>
<li><code>Master-CA</code>- ist die Zertifikationsinstanz, welche die Zertifikate ausstellt und signiert. Dies übernimmt mein Desktoprechner zuhause</li>
<li><code>openVPN-Server</code> - das übernimmit mein Homeserver</li>
<li><code>Clients</code> - mein Desktoprechner, mein Laptop sowie mein Büro-PC</li>
</ul>
</section>
<section id="installieren" class="level2">
<h2 class="anchored" data-anchor-id="installieren">Installieren</h2>
<p>Zunächst installiere ich die benötigten Pakete:</p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> apt install openvpn easy-rasa</span></code></pre></div>
<p>Ich nutze Arch, btw, daher nutze ich Pacman:</p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">pacman</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-S</span> openvpn easy-rsa </span></code></pre></div>
</section>
<section id="zertifikate-anlegen" class="level2">
<h2 class="anchored" data-anchor-id="zertifikate-anlegen">Zertifikate anlegen</h2>
<p>Bevor es wirklich los gehen kann, müssen die grundlegenden Zertifikate erstellt werden.</p>
<section id="master-ca" class="level3">
<h3 class="anchored" data-anchor-id="master-ca">Master CA</h3>
<p>Wir sind unsere eigene Zertifikationsinstanz, die alle weiteren Zertifikate für Server und Clients signiert. Diese Zertifikationsinstanz sollte auf einer anderen Maschine laufen als dem openVPN Server. Daher nutze ich meinen Desktop-PC zu hause dafür.</p>
<p>Wir erstellen zunächst das passende Verzeichnis unter <code>/etc/easy-rsa</code></p>
<div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb3-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> bash</span>
<span id="cb3-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mkdir</span> /etc/easy-rsa</span>
<span id="cb3-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">cd</span> /etc/easy-rsa</span></code></pre></div>
<p>… und erzeugen hier das Master-CA <code>ca.crt</code>:</p>
<div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb4-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">export</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">EASYRSA</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$(</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">pwd</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb4-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">easyrsa</span> init-pki</span>
<span id="cb4-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">easyrsa</span> build-ca</span></code></pre></div>
<p>Denke dir ein starkes Passwort für das Master-CA aus, und gib dir einen <em>Common Name</em>, ich habe da “Produnis” gewählt.</p>
<p>Die Datei <code>ca.crt</code> liegt nun im Unterordner <code>pki/</code></p>
</section>
<section id="serverzertifikat" class="level3">
<h3 class="anchored" data-anchor-id="serverzertifikat">Serverzertifikat</h3>
<p>Jetzt legen wir die Zertifikate für unseren openVPN-Server an und signieren sie mit unserem Master-CA:</p>
<div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb5-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">easyrsa</span> gen-req SERVERNAME nopass</span>
<span id="cb5-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">easyrsa</span> sign-req server SERVERNAME</span></code></pre></div>
<p>Wir müssen die Aktion mit <code>yes</code> bestätigen und das eben erzeugte Passwort des Master-CA eingeben.</p>
<p>Das erzeugte und signierte Zertifikat für den openVPN-Server liegt nun in <code>pki/private/SERVERNAME.key</code> bereit. Ebenfalls liegt dort die Datei <code>pki/private/ca.key</code>. Diese benötigen wir später noch, um weitere Zertifikate zu signieren.</p>
<p>Der openVPN-Server benötigt noch weitere Dateien für die Verschlüsslung des Netzwerks. Da diese Dateien auch von den Clients benötigt werden, erzeuge ich mir ein eigenes Verzeichnis hierfür, welches so heisst, wie das VPN-Netz, das ich erzeugen möchte. In meinem Fall soll das Netzwerk “produnis” heissen. Der Name ist egal, aber so verliert man nicht die Übersicht.</p>
<div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb6-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mkdir</span> /etc/easy-rsa/produnis</span>
<span id="cb6-2"></span>
<span id="cb6-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># diffie hellman für Perfect Forward Secrecy (PFS)</span></span>
<span id="cb6-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">openssl</span> dhparam <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-out</span> /etc/easy-rsa/produnis/dh.pem 2048</span>
<span id="cb6-5"></span>
<span id="cb6-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># HMAC key um Man-in-the-Middle-Angriffe zu unterbinden</span></span>
<span id="cb6-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">openvpn</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--genkey</span> secret /etc/easy-rsa/produnis/ta.key</span></code></pre></div>
<p>Jetzt kopieren wir alles auf den openVPN-Server. Folgende Dateien werden dort benötigt:</p>
<ul>
<li><code>/etc/easy-rsa/pki/private/SERVERNAME.key</code></li>
<li><code>/etc/easy-rsa/pki/issued/SERVERNAME.crt</code></li>
<li><code>/etc/easy-rsa/pki/ca.crt</code></li>
<li><code>/etc/easy-rsa/produnis/dh.pem</code></li>
<li><code>/etc/easy-rsa/produnis/ta.key</code></li>
</ul>
<p>Ich kopiere die Dateien zunächst ins <code>/tmp</code>-Verzeichnis des Servers.</p>
<div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb7-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scp</span> /etc/easy-rsa/pki/private/SERVERNAME.key /etc/easy-rsa/pki/issued/SERVERNAME.crt /etc/easy-rsa/pki/ca.crt /etc/easy-rsa/produnis/dh.pem /etc/easy-rsa/produnis/ta.key user@server:/tmp </span></code></pre></div>
</section>
</section>
<section id="server-einrichten" class="level2">
<h2 class="anchored" data-anchor-id="server-einrichten">Server einrichten</h2>
<p>Verbinde dich auf den Server und erstelle ein Unterverzeichnis in <code>/etc/openvpn/server/</code>, das wie das VPN-Netz heisst. Ich hatte ja <em>produnis</em> als Netznamen gewählt.</p>
<div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb8-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ssh</span> user@server</span>
<span id="cb8-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> bash</span>
<span id="cb8-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mkdir</span> /etc/openvpn/server/NETZNAME</span></code></pre></div>
<p>In diesen Ordner verschiebe ich die kopierten Dateien.</p>
<div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb9-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mv</span> /tmp/SERVERNAME.key /tmp/SERVERNAME.crt /tmp/ca.crt /tmp/dh.pem /tmp/ta.key /etc/openvpn/server/NETZNAME/</span></code></pre></div>
<p>Im “Hauptordner” <code>/etc/openvpn/server/</code> erstelle ich die Datei <code>produnis.conf</code> mit folgendem Inhalt:</p>
<div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb10-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">port</span> 1194</span>
<span id="cb10-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">proto</span> udp</span>
<span id="cb10-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">dev</span> tun</span>
<span id="cb10-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">server</span> 10.5.5.0 255.255.255.0 </span>
<span id="cb10-5"></span>
<span id="cb10-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ihr müsst "produnis" durch eure Namen ersetzen</span></span>
<span id="cb10-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ca</span> /etc/openvpn/server/produnis/ca.crt</span>
<span id="cb10-8"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">cert</span> /etc/openvpn/server/produnis/produnis.crt</span>
<span id="cb10-9"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">key</span> /etc/openvpn/server/produnis/produnis.key  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># This file should be kept secret</span></span>
<span id="cb10-10"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">dh</span> /etc/openvpn/server/produnis/dh.pem</span>
<span id="cb10-11"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">tls-crypt</span> /etc/openvpn/server/produnis/ta.key</span>
<span id="cb10-12"></span>
<span id="cb10-13"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">client-to-client</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># damit sich die clients untereinander sehen können</span></span>
<span id="cb10-14"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ifconfig-pool-persist</span> /etc/openvpn/server/produnis/ipp.txt</span>
<span id="cb10-15"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">keepalive</span> 10 120</span>
<span id="cb10-16"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">cipher</span> AES-256-CBC</span>
<span id="cb10-17"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">max-clients</span> 5</span>
<span id="cb10-18"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">persist-key</span></span>
<span id="cb10-19"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">persist-tun</span></span>
<span id="cb10-20"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">status</span> /etc/openvpn/server/produnis/openvpn-status.log</span>
<span id="cb10-21"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">verb</span> 3</span>
<span id="cb10-22"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">explicit-exit-notify</span> 1</span></code></pre></div>
<p>Stelle sicher, dass openVPN auf alle Dateien zugreifen kann:</p>
<div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb11-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">chown</span> openvpn:network <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-R</span> /etc/openvpn/server</span></code></pre></div>
<p>Starte den Server mittels</p>
<div class="sourceCode" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb12-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">openvpn</span> /etc/openvpn/server/produnis.conf</span></code></pre></div>
<section id="systemd" class="level3">
<h3 class="anchored" data-anchor-id="systemd">Systemd</h3>
<p>Alle Konfigurationsdateien liegen in <code>/etc/openvpn/server/</code>, z.B. <code>/etc/openvpn/server/produnis.conf</code>. Die passende systemd-Service-Unit heisst nun genauso wie die <code>.conf</code>-Datei (nur ohne <code>.conf</code>) <code>openvpn-server@servername.service</code>.</p>
<p>In meinem Fall also</p>
<div class="sourceCode" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb13-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">systemctl</span> start openvpn-server@produnis.service</span>
<span id="cb13-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">systemctl</span> status openvpn-server@produnis.service</span></code></pre></div>
</section>
</section>
<section id="clients-hinzufügen" class="level2">
<h2 class="anchored" data-anchor-id="clients-hinzufügen">Clients hinzufügen</h2>
<p>Auf der Master-CA-Maschine erzeugen wir nun weitere Zertifikate für jeden Client.</p>
<div class="sourceCode" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb14-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> bash</span>
<span id="cb14-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">cd</span> /etc/easy-rsa</span>
<span id="cb14-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">easyrsa</span> gen-req CLIENTNAME nopass</span>
<span id="cb14-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">easyrsa</span> sign-req client CLIENTNAME</span></code></pre></div>
<p>Wir müssen die Aktion mit <code>yes</code> bestätigen und das oben erzeugte Passwort des Master-CA eingeben.</p>
<p>Jetzt können wieder alle Dateien auf den Client übertragen werden. Benötigt werden</p>
<ul>
<li><code>/etc/easy-rsa/pki/private/CLIENTNAME.key</code></li>
<li><code>/etc/easy-rsa/pki/issued/CLIENTNAME.crt</code></li>
<li><code>/etc/easy-rsa/pki/ca.crt</code></li>
<li><code>/etc/easy-rsa/produnis/ta.key</code></li>
</ul>
<p>Ich kopiere diese Dateien zunächst ins <code>/tmp</code>-Verzeichnis auf dem Client:</p>
<div class="sourceCode" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb15-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scp</span> /etc/easy-rsa/pki/issued/CLIENTNAME.crt /etc/easy-rsa/pki/private/CLIENTNAME.key /etc/easy-rsa/pki/ca.crt /etc/easy-rsa/produnis/ta.key user@client:/tmp</span></code></pre></div>
<section id="konfiguration-der-clients" class="level3">
<h3 class="anchored" data-anchor-id="konfiguration-der-clients">Konfiguration der Clients</h3>
<p>Auf dem Client erstelle ich im Ordner <code>/etc/openvpn/client/</code> einen Unterordner <code>produnis</code>. In diesen lege ich alle Zertifikate.</p>
<div class="sourceCode" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb16-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ssh</span> user@client</span>
<span id="cb16-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> bash</span>
<span id="cb16-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mkdir</span> /etc/openvpn/client/produnis</span>
<span id="cb16-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mv</span> /tmp/ca.crt /tmp/ta.key /tmp/CLIENTNAME.key /tmp/CLIENTNAME.crt /etc/openvpn/client/produnis/</span></code></pre></div>
<p>Im “Hauptordner” <code>/etc/openvpn/client/</code> erstelle ich die Datei <code>produnis.conf</code> mit folgendem Inhalt:</p>
<div class="sourceCode" id="cb17" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb17-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">client</span></span>
<span id="cb17-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">dev</span> tun</span>
<span id="cb17-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">proto</span> udp</span>
<span id="cb17-4"></span>
<span id="cb17-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">remote</span> mein.server.de 1194  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ersetze mit Adresse des openVPN-Server</span></span>
<span id="cb17-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ca</span> /etc/openvpn/client/produnis/ca.crt</span>
<span id="cb17-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">cert</span> /etc/openvpn/client/produnis/CLIENTNAME.crt</span>
<span id="cb17-8"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">key</span> /etc/openvpn/client/produnis/CLIENTNAME.key</span>
<span id="cb17-9"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">tls-crypt</span> /etc/openvpn/client/produnis/ta.key</span>
<span id="cb17-10"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">cipher</span> AES-256-CBC</span>
<span id="cb17-11"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">resolv-retry</span> infinite</span>
<span id="cb17-12"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">nobind</span></span>
<span id="cb17-13"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">persist-key</span></span>
<span id="cb17-14"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">persist-tun</span></span>
<span id="cb17-15"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">tun-mtu</span> 1350 <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Unitymedia/Vodafone</span></span>
<span id="cb17-16"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">verb</span> 3</span></code></pre></div>
<p>Stelle sicher, dass openVPN auf alle Dateien zugreifen kann:</p>
<div class="sourceCode" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb18-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">chown</span> openvpn:network <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-R</span> /etc/openvpn/client</span></code></pre></div>
<p>Starte den Client mittels</p>
<div class="sourceCode" id="cb19" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb19-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">openvpn</span> /etc/openvpn/client/produnis.conf</span></code></pre></div>
</section>
<section id="mit-systemd-starten" class="level3">
<h3 class="anchored" data-anchor-id="mit-systemd-starten">Mit Systemd starten</h3>
<p>Alle Konfigurationsdateien liegen in <code>/etc/openvpn/client/</code>, z.B. <code>/etc/openvpn/client/produnis.conf</code>. Die passende systemd-Service-Unit heisst nun genauso wie die <code>.conf</code>-Datei (nur ohne <code>.conf</code>) <code>openvpn-client@produnis.service</code>.</p>
<p>In meinem Fall also wieder</p>
<div class="sourceCode" id="cb20" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb20-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> systemctl start openvpn-client@produnis.service</span>
<span id="cb20-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> systemctl status openvpn-client@produnis.service</span></code></pre></div>
</section>
</section>
<section id="statische-ip-adresse-für-die-clients-festlegen" class="level2">
<h2 class="anchored" data-anchor-id="statische-ip-adresse-für-die-clients-festlegen">statische IP-Adresse für die Clients festlegen</h2>
<p>Dies ist eine Art DHCP-light, wir teilen jedem Client eine feste IP innerhalb des VPN-Netzes zu.</p>
<p>Erstelle auf dem Server ein Unterverzeichnis <code>ccd</code> (<strong>c</strong>lient <strong>c</strong>onfig <strong>d</strong>ir) und lege dort je eine Datei für jeden Client an.</p>
<div class="sourceCode" id="cb21" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb21-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mkdir</span> /etc/openvpn/server/produnis/ccd</span>
<span id="cb21-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">cd</span>  /etc/openvpn/server/produnis/ccd</span>
<span id="cb21-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nano</span> CLIENTNAME</span></code></pre></div>
<p><code>CLIENTNAME</code> ist dabei der Name, den du beim Erzeugen der Zertifikate verwendet hast. Anhand des Zertifikats erkennt der Server den Client.</p>
<p>In die Datei schreibst du:</p>
<div class="sourceCode" id="cb22" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb22-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ifconfig-push</span> 10.5.5.x 10.5.5.1</span></code></pre></div>
<p>wobei du <code>x</code> durch die gewünschte IP ersetzt. Die zweite IP ist die des VPN-Servers, also immer <code>10.5.5.1</code>.</p>
<p>Damit der Server über unsere IP-Listen Bescheid weiss, muss <code>/etc/openvpn/server/produnis.conf</code> um folgende Zeile erweitert werden:</p>
<div class="sourceCode" id="cb23" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb23-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">client-config-dir</span> /etc/openvpn/server/produnis/ccd</span></code></pre></div>
<p>Anschließend muss openVPN neu gestartet werden, z.B. mittels</p>
<div class="sourceCode" id="cb24" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb24-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">systemctl</span> restart openvpn-server@produnis.service</span></code></pre></div>
</section>
<section id="firewall-anpassen" class="level2">
<h2 class="anchored" data-anchor-id="firewall-anpassen">Firewall anpassen</h2>
<p>Falls ihr eine Firewall benutzt (und ich hoffe doch sehr, dass dies der Fall ist), muss diese für openVPN angepasst werden. Einerseits müssen Ports freigegeben werden (standardmäßig <code>1194 udp</code>), anderseits müssen wir intern <code>NAT</code> einrichten, wenn der Internetverkehr über den Tunnel geroutet werden soll.</p>
<section id="iptables" class="level3">
<h3 class="anchored" data-anchor-id="iptables">iptables</h3>
<p>Die iptables-Firewall muss auf dem Server und auf den Clients angepasst werden, damit openVPN funktioniert:</p>
<div class="sourceCode" id="cb25" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb25-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">## openvpn general settings für Server und Client</span></span>
<span id="cb25-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">iptables</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-A</span> INPUT <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-i</span> tun+ <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-j</span> ACCEPT</span>
<span id="cb25-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">iptables</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-A</span> FORWARD <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-i</span> tun+ <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-j</span> ACCEPT</span>
<span id="cb25-4"></span>
<span id="cb25-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">## nur auf dem Server nächste Zeile ausführen</span></span>
<span id="cb25-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">## Dies setzt das NAT auf, damit Internet durch den Tunnel geroutet wird</span></span>
<span id="cb25-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#iptables -t nat -A POSTROUTING -s 10.5.5.0/24 -o eth0 -j MASQUERADE </span></span>
<span id="cb25-8"></span>
<span id="cb25-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">## auf Server und Client muss Port 1194 fuer openVPN geöffnet werden</span></span>
<span id="cb25-10"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">iptables</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-A</span> INPUT <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-i</span> eth0 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-p</span> udp <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--destination-port</span> 1194 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-j</span> ACCEPT</span></code></pre></div>
<p>Wenn euer Device nicht <code>eth0</code> heisst, müsst ihr den Befehl entsprechend anpassen.</p>
</section>
<section id="ufw" class="level3">
<h3 class="anchored" data-anchor-id="ufw">ufw</h3>
<p>Die ufw-Firewall muss auf dem Server und auf den Clients angepasst werden, damit openVPN funktioniert:</p>
<div class="sourceCode" id="cb26" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb26-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># openVPN</span></span>
<span id="cb26-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> ufw allow 1194</span>
<span id="cb26-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> ufw allow out 1194/udp</span></code></pre></div>
<p>Auf dem Server müssen noch drei weitere Einstellungen getroffen werden, damit das Netz funktioniert.</p>
<ol type="1">
<li><code>/etc/default/ufw</code></li>
</ol>
<div class="sourceCode" id="cb27" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb27-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nano</span> /etc/default/ufw </span>
<span id="cb27-2"></span>
<span id="cb27-3"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">DEFAULT_FORWARD_POLICY</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ACCEPT"</span></span></code></pre></div>
<ol start="2" type="1">
<li><code>/etc/ufw/before.rules</code>, füge die folgenden Zeilen <strong>vor</strong> der <code>*filter</code>-Sektion ein, um das <code>NAT</code> zu aktivieren:</li>
</ol>
<div class="sourceCode" id="cb28" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb28-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nano</span> /etc/ufw/before.rules</span>
<span id="cb28-2"></span>
<span id="cb28-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># NAT-Tabelle hinzufügen</span></span>
<span id="cb28-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">*nat</span></span>
<span id="cb28-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:POSTROUTING</span> ACCEPT <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">[</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">0:0</span><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">]</span></span>
<span id="cb28-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># OpenVPN-Regeln hinzufügen</span></span>
<span id="cb28-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">-A</span> POSTROUTING <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-s</span> 10.5.5.0/24 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> eth0 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-j</span> MASQUERADE</span>
<span id="cb28-8"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">COMMIT</span></span></code></pre></div>
<p>Wenn euer Device nicht <code>eth0</code> heisst, müsst ihr den Befehl entsprechend anpassen.</p>
<ol start="3" type="1">
<li><code>/etc/ufw/sysctl.conf</code></li>
</ol>
<div class="sourceCode" id="cb29" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb29-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nano</span> /etc/ufw/sysctl.conf</span>
<span id="cb29-2"></span>
<span id="cb29-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">net/ipv4/ip_forward=1</span></span>
<span id="cb29-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">net/ipv6/conf/default/forwarding=1</span></span>
<span id="cb29-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">net/ipv6/conf/all/forwarding=1</span></span></code></pre></div>
</section>
</section>
<section id="fertig" class="level2">
<h2 class="anchored" data-anchor-id="fertig">Fertig</h2>
<p>Jetzt sollten sich alle Clients mit dem Server verbinden und sich untereinander “sehen” können. Da jeder Client von mir eine fest IP-Adresse zugewiesen bekommen hat, kann ich nun easy per ssh von Client zu Client oder auf den Server verbinden. Genau so, wie ich es wollte.</p>
<section id="gesamten-traffic-über-das-vpn-routen" class="level3">
<h3 class="anchored" data-anchor-id="gesamten-traffic-über-das-vpn-routen">gesamten Traffic über das VPN routen</h3>
<p>Damit ein Client seinen gesamten Traffic über den VPN tunnelt, muss in der Client-Config folgende Zeile ergänzt werden:</p>
<div class="sourceCode" id="cb30" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb30-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">redirect-gateway</span> def1 <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># leitet gesamten Datenverkehr über das VPN</span></span></code></pre></div>
<p>Das <code>def1</code> steht für “default route” und muss nicht weiter angepasst werden.</p>
</section>
</section>
<section id="siehe-auch" class="level2">
<h2 class="anchored" data-anchor-id="siehe-auch">siehe auch</h2>
<ul>
<li>Im <a href="../2024-03-19-openvpn-android/">nächsten Blogpost</a> zeige ich, wie ich Handy und Tablet unter Android dem VPN hinzugefügt und IPv6 aktiviert habe.</li>
<li>Weil es so schön war, hab ich alles nochmal mit <a href="../2024-03-22-wireguard/">Wireguard nachgebaut</a>.</li>
</ul>
</section>
<section id="weblinks" class="level2">
<h2 class="anchored" data-anchor-id="weblinks">Weblinks</h2>
<ul>
<li><a href="https://wiki.archlinux.org/title/OpenVPN" class="uri">https://wiki.archlinux.org/title/OpenVPN</a></li>
<li><a href="https://wiki.archlinux.org/index.php/Easy-RSA" class="uri">https://wiki.archlinux.org/index.php/Easy-RSA</a></li>
<li><a href="https://www.itsfullofstars.de/2018/09/openvpn-assign-static-ip-to-client/" class="uri">https://www.itsfullofstars.de/2018/09/openvpn-assign-static-ip-to-client/</a></li>
<li><a href="https://bbs.archlinux.org/viewtopic.php?id=293930" class="uri">https://bbs.archlinux.org/viewtopic.php?id=293930</a></li>
<li><a href="https://requestforcomments.de/archives/682" class="uri">https://requestforcomments.de/archives/682</a></li>
</ul>
            <br><center>
            <div class="matrixfoot" id="matrixfooter">
            <a href="https://matrix.to/#/#produnis-blog:tchncs.de">
            <img src="https://www.produnis.de/images/Matrix.webp" width="60">
            </a>
            Diskussion per Matrix unter <a href="https://matrix.to/#/#produnis-blog:tchncs.de">https://matrix.to/#/#produnis-blog:tchncs.de</a>
            </div>
            </center><br>&nbsp;
        


</section>

 ]]></description>
  <category>openvpn</category>
  <category>Heimserver</category>
  <category>ubuntuusers</category>
  <guid>https://www.produnis.de/blog/posts/2024-03-16-openvpn/</guid>
  <pubDate>Sat, 16 Mar 2024 18:24:00 GMT</pubDate>
  <media:content url="https://www.produnis.de/blog/posts/2024-03-16-openvpn/openvpnlogo.webp" medium="image" type="image/webp"/>
</item>
<item>
  <title>Mein KDE Plasma Panel</title>
  <dc:creator>Joe Slam</dc:creator>
  <link>https://www.produnis.de/blog/posts/2024-02-20-PlasmaPanel/</link>
  <description><![CDATA[ 





<p>Ich verwende KDE (also Plasma) als Desktop. Ich habe eh begrenzten vertikalen Platz (meine Bildschirme sind breiter als hoch), und durch ein Panel oben oder unten würde dieser Platz noch weniger werden. Daher habe ich mir ein seitliches Panel am linken Bildschirmrand eingerichtet.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://www.produnis.de/blog/posts/2024-02-20-PlasmaPanel/MyPanel2.webp" class="img-fluid figure-img"></p>
<figcaption>#showyourdesktop</figcaption>
</figure>
</div>
<p>Sieht gut aus, oder?</p>
<section id="nachbauen" class="level2">
<h2 class="anchored" data-anchor-id="nachbauen">Nachbauen</h2>
<ul>
<li>Um ein seitliches Panel zu erstellen führt ihr in einem leeren Bereich eures Desktops einen Rechtsklick aus und wählt “<code>Kontrolleiste hinzfügen -&gt; leere Kontrollleiste</code>”.</li>
<li>Dies macht ihr so lange, bis eine seitliche Leiste links oder rechts entsteht (zuerst wird oben eine entstehen, dann links, dann rechts).</li>
<li>Die nicht benötigten neuen Leisten könnt ihr direkt wieder löschen.</li>
<li>Mein Panel hat eine Breite von <code>100</code></li>
</ul>
<section id="widgets" class="level3">
<h3 class="anchored" data-anchor-id="widgets">Widgets</h3>
<p>Mein Panel besteht aus folgenden Widgets:</p>
<table class="caption-top table">
<colgroup>
<col style="width: 44%">
<col style="width: 16%">
<col style="width: 37%">
</colgroup>
<thead>
<tr class="header">
<th>Panel</th>
<th colspan="2">Widgets</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><img src="https://www.produnis.de/blog/posts/2024-02-20-PlasmaPanel/MyPanel1.webp" class="img-fluid" width="100"></td>
<td colspan="2"><ul>
<li><p>Analoge Uhr</p></li>
<li><p>Digitale Uhr</p></li>
<li><p>Systemmonitor-Sensoren</p>
<ul>
<li>Azeige-Stil: <code>Gitter</code></li>
<li>Gitter-Stil: <code>Liniendiagramm</code></li>
<li>Sensoren:
<ul>
<li><code>Gesamtauslastung</code></li>
<li><code>Warteauslastung</code></li>
<li><code>Download-Rate</code></li>
<li><code>Upload-Rate</code></li>
</ul></li>
</ul></li>
<li><p>Abstandhalter (Breite 10)</p></li>
<li><p>Systemabschnitt der Kontrollleiste</p></li>
<li><p>Abstandhalter</p></li>
<li><p>Fensterleiste</p></li>
<li><p>Anwendungsstarter</p></li>
</ul></td>
</tr>
</tbody>
</table>
<p>Weitere Desktopbilder finden sich bei Mastodon unter dem Hashtag <code>#showyourdesktop</code>. Wie sieht euer Desktop aus?</p>
</section>
</section>
<section id="weblinks" class="level2">
<h2 class="anchored" data-anchor-id="weblinks">Weblinks</h2>
<ul>
<li><a href="https://kde.org" class="uri">https://kde.org</a></li>
</ul>
            <br><center>
            <div class="matrixfoot" id="matrixfooter">
            <a href="https://matrix.to/#/#produnis-blog:tchncs.de">
            <img src="https://www.produnis.de/images/Matrix.webp" width="60">
            </a>
            Diskussion per Matrix unter <a href="https://matrix.to/#/#produnis-blog:tchncs.de">https://matrix.to/#/#produnis-blog:tchncs.de</a>
            </div>
            </center><br>&nbsp;
        


</section>

 ]]></description>
  <category>KDE</category>
  <category>ubuntuusers</category>
  <guid>https://www.produnis.de/blog/posts/2024-02-20-PlasmaPanel/</guid>
  <pubDate>Mon, 19 Feb 2024 23:00:00 GMT</pubDate>
  <media:content url="https://www.produnis.de/blog/posts/2024-02-20-PlasmaPanel/MyPanel2.webp" medium="image" type="image/webp"/>
</item>
<item>
  <title>Bedienungsanleitung für die Hallenuhr im Schürenkamp</title>
  <dc:creator>Joe Slam</dc:creator>
  <link>https://www.produnis.de/blog/posts/2024-02-10-Hallenuhr-Schuerenkamp/</link>
  <description><![CDATA[ 





<blockquote class="blockquote">
<p>Sporthalle Schürenkamp<br> Grenzstraße 1 <br> D-45881 Gelsenkirchen</p>
</blockquote>
<div class="cell page-columns page-full">
<div class="cell-output-display column-body">
<div class="leaflet html-widget html-fill-item-overflow-hidden html-fill-item" id="htmlwidget-1525f5edf395c328b17e" style="width:100%;height:464px;"></div>
<script type="application/json" data-for="htmlwidget-1525f5edf395c328b17e">{"x":{"options":{"crs":{"crsClass":"L.CRS.EPSG3857","code":null,"proj4def":null,"projectedBounds":null,"options":{}}},"calls":[{"method":"addTiles","args":["https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",null,null,{"minZoom":0,"maxZoom":18,"tileSize":256,"subdomains":"abc","errorTileUrl":"","tms":false,"noWrap":false,"zoomOffset":0,"zoomReverse":false,"opacity":1,"zIndex":1,"detectRetina":false,"attribution":"&copy; <a href=\"https://openstreetmap.org/copyright/\">OpenStreetMap<\/a>,  <a href=\"https://opendatacommons.org/licenses/odbl/\">ODbL<\/a>"}]},{"method":"addMarkers","args":[51.51611,7.08331,null,null,null,{"interactive":true,"draggable":false,"keyboard":true,"title":"","alt":"","zIndexOffset":0,"opacity":1,"riseOnHover":false,"riseOffset":250},"Sporthalle Schürenkamp",null,null,null,null,{"interactive":false,"permanent":false,"direction":"auto","opacity":1,"offset":[0,0],"textsize":"10px","textOnly":false,"className":"","sticky":true},null]}],"limits":{"lat":[51.51611,51.51611],"lng":[7.08331,7.08331]}},"evals":[],"jsHooks":[]}</script>
</div>
</div>
<section id="hallenuhr-am-schürenkamp-bodet-bt-5010" class="level2">
<h2 class="anchored" data-anchor-id="hallenuhr-am-schürenkamp-bodet-bt-5010">Hallenuhr am Schürenkamp (<code>Bodet BT 5010</code>)</h2>
<p>Die Bedientafel der Hallenuhr im Schürenkamp ist schon ziemlich abgerockt.</p>
<div id="fig-schuerenkamp1" class="quarto-float quarto-figure quarto-figure-center anchored">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-schuerenkamp1-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://www.produnis.de/blog/posts/2024-02-10-Hallenuhr-Schuerenkamp/Schuerenkamp01.webp" class="img-fluid figure-img">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-schuerenkamp1-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Abbildung&nbsp;1: Schalttafel der Hallenuhr am Schürenkamp
</figcaption>
</figure>
</div>
</section>
<section id="die-zeit-einstellen" class="level2">
<h2 class="anchored" data-anchor-id="die-zeit-einstellen">Die Zeit einstellen</h2>
<p>Über den Plus-Knopf (<code>Preselection Presetting</code>) oben links kann die gewünschte Länge der Halbzeit eingestellt werden (Abbildung&nbsp;2).</p>
<div id="fig-schuerenkamp2" class="quarto-float quarto-figure quarto-figure-center anchored">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-schuerenkamp2-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://www.produnis.de/blog/posts/2024-02-10-Hallenuhr-Schuerenkamp/Schuerenkamp02.webp" class="img-fluid figure-img">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-schuerenkamp2-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Abbildung&nbsp;2: Zeit einstellen
</figcaption>
</figure>
</div>
<p>Mit jedem Tastendruck zählt die Uhr 1 Minute hoch. Eine Handballhalbzeit dauert 30 Minuten, in der Jugend 20 Minunten.</p>
<p>Ist die korrekte Minutenzahl eingestellt, muss die <code>RESET</code>-Taste 5 Sekunden lang gedrückt werden (Abbildung&nbsp;3).</p>
<div id="fig-schuerenkamp3" class="quarto-float quarto-figure quarto-figure-center anchored">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-schuerenkamp3-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://www.produnis.de/blog/posts/2024-02-10-Hallenuhr-Schuerenkamp/Schuerenkamp03.webp" class="img-fluid figure-img">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-schuerenkamp3-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Abbildung&nbsp;3: RESET Taste 5 Sekunden drücken
</figcaption>
</figure>
</div>
<p>Die Uhr springt dabei auf <code>0:00</code> zurück.</p>
<p>Die Zeit kann jetzt mit dem <code>Start Stop</code>-Knopf gestartet und gestoppt werden.</p>
<div id="fig-schuerenkamp4" class="quarto-float quarto-figure quarto-figure-center anchored">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-schuerenkamp4-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://www.produnis.de/blog/posts/2024-02-10-Hallenuhr-Schuerenkamp/Schuerenkamp04.webp" class="img-fluid figure-img">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-schuerenkamp4-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Abbildung&nbsp;4: Start-Stop-Taste
</figcaption>
</figure>
</div>
</section>
<section id="tore-zählen" class="level2">
<h2 class="anchored" data-anchor-id="tore-zählen">Tore zählen</h2>
<p>Unten rechts (<code>Score</code>) können die Tore für Heim und Gast gezählt werden (Abbildung&nbsp;5)</p>
<div id="fig-schuerenkamp5" class="quarto-float quarto-figure quarto-figure-center anchored">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-schuerenkamp5-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://www.produnis.de/blog/posts/2024-02-10-Hallenuhr-Schuerenkamp/Schuerenkamp05.webp" class="img-fluid figure-img">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-schuerenkamp5-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Abbildung&nbsp;5: Tore für Heim und Gast zählen
</figcaption>
</figure>
</div>
<section id="tore-zurücknehmen" class="level3">
<h3 class="anchored" data-anchor-id="tore-zurücknehmen">Tore zurücknehmen</h3>
<p>Soll ein Tor zurückgenommen werden, muss</p>
<ol type="1">
<li>der C-Knopf (<code>Correction</code>) gedrückt werden (Abbildung&nbsp;6),</li>
</ol>
<div id="fig-schuerenkamp6" class="quarto-float quarto-figure quarto-figure-center anchored">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-schuerenkamp6-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://www.produnis.de/blog/posts/2024-02-10-Hallenuhr-Schuerenkamp/Schuerenkamp06.webp" class="img-fluid figure-img">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-schuerenkamp6-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Abbildung&nbsp;6: Korrektur-Knopf
</figcaption>
</figure>
</div>
<ol start="2" type="1">
<li><p>über die Tore-Knöpfe (Abbildung&nbsp;5) die Tore heruntergezählt werden,</p></li>
<li><p>erneut der C-Knopf gedrückt werden.</p></li>
</ol>
</section>
</section>
<section id="zeitstrafen" class="level2">
<h2 class="anchored" data-anchor-id="zeitstrafen">Zeitstrafen</h2>
<p>Zeitstrafen für Heim und Gast können über die <code>Fouls</code>-Knöpfe rechts (über den Tor-Knöpfen) (Abbildung&nbsp;7) gesetzt werden.</p>
<div id="fig-schuerenkamp7" class="quarto-float quarto-figure quarto-figure-center anchored">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-schuerenkamp7-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://www.produnis.de/blog/posts/2024-02-10-Hallenuhr-Schuerenkamp/Schuerenkamp07.webp" class="img-fluid figure-img">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-schuerenkamp7-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Abbildung&nbsp;7: Zeitstrafen
</figcaption>
</figure>
</div>
</section>
<section id="team-auszeiten" class="level2">
<h2 class="anchored" data-anchor-id="team-auszeiten">Team-Auszeiten</h2>
<p>Team-Auszeiten können über die mittleren Knöpfe (<code>Time Out</code>) (Abbildung&nbsp;8) für Heim und Gast gesetzt werden.</p>
<div id="fig-schuerenkamp9" class="quarto-float quarto-figure quarto-figure-center anchored">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-schuerenkamp9-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://www.produnis.de/blog/posts/2024-02-10-Hallenuhr-Schuerenkamp/Schuerenkamp09.webp" class="img-fluid figure-img">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-schuerenkamp9-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Abbildung&nbsp;8: Team-Auszeiten
</figcaption>
</figure>
</div>
<p>Jedoch geht dies nicht automatisch. Der Ablauf lautet:</p>
<ol type="1">
<li>Zeit stoppen (Abbildung&nbsp;4)</li>
<li>Hupe betätigen (Abbildung&nbsp;9)</li>
<li>Team-Auszeit setzen (Abbildung&nbsp;8)</li>
</ol>
<p>Die Uhr zählt nun unsichtbar 1 Minute herunter. Nach 50 Sekunden ertönt die Hupe kurz, nach 1 Minute lang.</p>
</section>
<section id="hupen" class="level2">
<h2 class="anchored" data-anchor-id="hupen">Hupen</h2>
<p>Die Hupe befindet sich auf der linken Seite (Abbildung&nbsp;9).</p>
<div id="fig-schuerenkamp8" class="quarto-float quarto-figure quarto-figure-center anchored">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-schuerenkamp8-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<img src="https://www.produnis.de/blog/posts/2024-02-10-Hallenuhr-Schuerenkamp/Schuerenkamp08.webp" class="img-fluid figure-img">
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-schuerenkamp8-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Abbildung&nbsp;9: Hupe
</figcaption>
</figure>
</div>
</section>
<section id="pdf" class="level2">
<h2 class="anchored" data-anchor-id="pdf">PDF</h2>
<p>Eine PDF-Version dieser Anleitung zum Ausdrucken gibt es <a href="https://www.produnis.de/blog/posts/2024-02-10-Hallenuhr-Schuerenkamp/Handball-Uhr-Schuerenkamp.pdf">hier</a>.</p>
</section>
<section id="weblinks" class="level2">
<h2 class="anchored" data-anchor-id="weblinks">Weblinks</h2>
<div class="quarto-video ratio ratio-16x9"><iframe data-external="1" src="https://www.youtube.com/embed/K0wgcCS5FU4" title="" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe></div>
<ul>
<li><a href="https://www.youtube.com/watch?v=K0wgcCS5FU4" class="uri">https://www.youtube.com/watch?v=K0wgcCS5FU4</a></li>
<li><a href="https://www.handball.net/hallen/handball4all.westfalen.2191" class="uri">https://www.handball.net/hallen/handball4all.westfalen.2191</a></li>
<li><a href="https://www.produnis.de/blog/posts/2024-02-10-Hallenuhr-Schuerenkamp/Handball-Uhr-Schuerenkamp.pdf" class="uri">https://www.produnis.de/blog/posts/2024-02-10-Hallenuhr-Schuerenkamp/Handball-Uhr-Schuerenkamp.pdf</a></li>
</ul>
            <br><center>
            <div class="matrixfoot" id="matrixfooter">
            <a href="https://matrix.to/#/#produnis-blog:tchncs.de">
            <img src="https://www.produnis.de/images/Matrix.webp" width="60">
            </a>
            Diskussion per Matrix unter <a href="https://matrix.to/#/#produnis-blog:tchncs.de">https://matrix.to/#/#produnis-blog:tchncs.de</a>
            </div>
            </center><br>&nbsp;
        


</section>

 ]]></description>
  <category>Jean Pütz</category>
  <guid>https://www.produnis.de/blog/posts/2024-02-10-Hallenuhr-Schuerenkamp/</guid>
  <pubDate>Fri, 09 Feb 2024 23:00:00 GMT</pubDate>
  <media:content url="https://www.produnis.de/blog/posts/2024-02-10-Hallenuhr-Schuerenkamp/Schuerenkamp01.webp" medium="image" type="image/webp"/>
</item>
<item>
  <title>ArchLinux auf einem Laptop installieren (mit Verschlüsselung)</title>
  <dc:creator>Joe Slam</dc:creator>
  <link>https://www.produnis.de/blog/posts/2024-02-09-ArchLinux-installieren/</link>
  <description><![CDATA[ 





<p>In diesem Blogpost möchte ich zeigen, wie ich ArchLinux auf einem Laptop installiere. Hierbei erfolgt die Installation auf eine verschlüsselte Partition, was bei tragbaren Geräten empfehlenswert ist. So fallen keine Daten in falsche Hände, falls das Gerät geklaut oder vergessen wird.</p>
<section id="image-auf-stick-flashen" class="level2">
<h2 class="anchored" data-anchor-id="image-auf-stick-flashen">Image auf Stick flashen</h2>
<ul>
<li>Lade dir ein aktuelles Arch-Image herunter, siehe <a href="https://archlinux.org/download/" class="uri">https://archlinux.org/download/</a></li>
<li>Stecke einen USB-Stick in dein Gerät und checke dessen <code>/dev/</code>-Adresse mittels</li>
</ul>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> lsblk</span></code></pre></div>
<p>Das kann dann z.B. so aussehen:</p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">NAME</span>            MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINTS  </span>
<span id="cb2-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">sda</span>             259:0    0 931,5G  0 disk</span>
<span id="cb2-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">sdb</span>               8:0    1   7,4G  0 disk </span></code></pre></div>
<p>In diesem Beispiel ist <code>sda</code> die Festplatte, und <code>sdb</code> der USB-Stick. Bei euch kann das durchaus anders aussehen.</p>
<ul>
<li>Flashe das Arch-Image auf den Stick, z.B. mittels</li>
</ul>
<div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb3-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> dd if=archlinux<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">*</span>.iso of=/dev/sdb</span></code></pre></div>
<p>wobei <code>sdb</code> bei euch evtl. entsprechend angepasst werden muss.</p>
</section>
<section id="booten-vom-stick" class="level2">
<h2 class="anchored" data-anchor-id="booten-vom-stick">booten vom Stick</h2>
<p>Stecke den Stick in den Laptop, und wähle beim Starten den Stick als Bootquelle aus. Bei mir funktioniert das, indem ich <code>F12</code> beim Starten gedrückt halte.</p>
<p>Es sollte sich recht bald das Arch-Bootmenu melden</p>
<p><img src="https://www.produnis.de/blog/posts/2024-02-09-ArchLinux-installieren/Arch-Linux-Boot-Screen-1.webp" class="img-fluid"></p>
<p>Wähle den ersten Eintrag aus und warte, bis dich die Kommandozeile begrüßt.</p>
</section>
<section id="netzwerkverbindung-herstellen" class="level2">
<h2 class="anchored" data-anchor-id="netzwerkverbindung-herstellen">Netzwerkverbindung herstellen</h2>
<p>Ist Arch gestartet, stellen wir als erstes eine Netzwerkverbindung her. Das Netzwerk brauchen wir, um frische Installationspakete zu holen, aber auch, um uns gleich per SSH auf die neue Kiste einzuloggen.</p>
<section id="lan" class="level3">
<h3 class="anchored" data-anchor-id="lan">LAN</h3>
<p>Wenn ein LAN-Kabel bereit liegt, kann dieses einfach eingesteckt werden, und die Verbindung sollte direkt funktionieren.</p>
</section>
<section id="wlan" class="level3">
<h3 class="anchored" data-anchor-id="wlan">WLAN</h3>
<p>Möchtet ihr euch mit einem WLAN verbinden, geht dies am Einfachsten mit dem Befehl</p>
<div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb4-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> iwctl</span></code></pre></div>
<p>Um den WLAN-Devicenamen herauszufinden hilft der Befehl</p>
<div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb5-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> devices list</span></code></pre></div>
<p>Meistens heisst das Device <code>wlan0</code>.</p>
<p>Stelle eine Verbindung zum WLAN her mittels</p>
<div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb6-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> station wlan0 connect <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>SSID<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span></code></pre></div>
<p>Gib das Passwort des WLANs ein. Wenn alles fertig ist, verlasse das Proggi mittels</p>
<div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb7-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> exit</span></code></pre></div>
</section>
</section>
<section id="ssh" class="level2">
<h2 class="anchored" data-anchor-id="ssh">SSH</h2>
<p>Ich verbinde mich an dieser Stelle gerne mittels SSH auf den Laptop. Stelle sicher, dass <code>sshd</code> läuft,</p>
<div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb8-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> systemctl start sshd</span></code></pre></div>
<p>Setze ein temporäres Admin-Passwort mittels</p>
<div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb9-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> passwd</span></code></pre></div>
<p>Finde die IP-Adresse des Laptops heraus, zB mittels</p>
<div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb10-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> ip a</span></code></pre></div>
<p>Logge dich von einem anderen PC auf die neue Kiste ein mittels</p>
<div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb11-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> ssh root@IP-ADRESSE</span></code></pre></div>
</section>
<section id="partitionierung-der-festplatte" class="level2">
<h2 class="anchored" data-anchor-id="partitionierung-der-festplatte">Partitionierung der Festplatte</h2>
<p>Nun partitionieren wir die Festplatte. Wir wollen 2 Partitionen erstellen,</p>
<ul>
<li>eine <code>EFI</code>-Partition zum Booten,</li>
<li>und eine verschlüsselte <code>root</code>-Partition für das Archsystem.</li>
</ul>
<p>Zunächst finden wir wieder die <code>/dev/</code>-Bezeichnungen der Laptopfestplatte heraus mittels</p>
<div class="sourceCode" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb12-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> lsblk</span></code></pre></div>
<div class="sourceCode" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb13-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">NAME</span>            MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINTS</span>
<span id="cb13-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">sda</span>             259:0    0 931,5G  0 disk </span>
<span id="cb13-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">sdb</span>               8:0    1   7,4G  0 disk  </span>
<span id="cb13-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">├─sdb1</span>            8:1    1   917M  0 part  </span>
<span id="cb13-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">└─sdb2</span>            8:2    1    15M  0 part  </span></code></pre></div>
<p>In diesem Beispiel ist <code>sda</code> die Festplatte des Laptops und <code>sdb</code> der Boot-Stick. Wir wollen also <code>/dev/sda</code> partitionieren.</p>
<p>Starte <code>gdisk</code> mittels</p>
<div class="sourceCode" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb14-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> gdisk /dev/sda</span></code></pre></div>
<p>Wir können mit <code>p</code> schauen, welche Partitionen schon auf der Platte sind. Meine Platte ist neu und leer, und daher gibt es nichts zu sehen. Möchtet ihr eine bereits gebrauchte Festplatte benutzen, könnt ihr die vorhandenen Partitionen mittels <code>d</code> löschen.</p>
<p>Wir erstellen eine neue Partition mittels <code>n</code>.</p>
<ul>
<li>die erste Partition wird unsere Boot-Partition.</li>
<li>die voreingestellte Partitionsnummer <code>1</code> ist korrekt, so dass wir einfach <code>ENTER</code> drücken können.</li>
<li>ebenfalls korrekt ist der erste Sektor. Auch diesen können wir mittels <code>ENTER</code> bestätigen.</li>
<li>beim “letzten Sektor” geben wir <code>+512M</code> ein, damit die Partition 512 MB groß wird.</li>
<li>der Partitionscode im Hexformat lautet: <code>ef00</code> (EFI-Partition)</li>
</ul>
<p>Wir erstellen eine weitere Partition mittels <code>n</code>.</p>
<ul>
<li>diese zweite Partition soll die verschlüsselte Systempartition werden.</li>
<li>die voreingestellte Partitionsnummer <code>2</code> ist korrekt, so dass wir einfach <code>ENTER</code> drücken können.</li>
<li>ebenfalls korrekt ist der erste Sektor. Auch diesen können wir mittels <code>ENTER</code> bestätigen</li>
<li>und auch der letzte Sektor ist korrekt, weil wir den gesamten Rest der Festplatte verwenden möchten. Wir können also einfach <code>ENTER</code> drücken können.</li>
<li>der Partitionscode im Hexformat lautet: <code>8309</code> (LUKS-Partition)</li>
</ul>
<p>Wir können mittels <code>p</code> überprüfen, ob alles richtig ist.</p>
<p>Zum Schluss schreiben wir die Partitionstabelle mittels <code>w</code>.</p>
</section>
<section id="verschlüsselung" class="level2">
<h2 class="anchored" data-anchor-id="verschlüsselung">Verschlüsselung</h2>
<p>Um sicher zu sein, dass alles klappen wird, laden wir die Encryption-Module</p>
<div class="sourceCode" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb15-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> modprobe dm-crypt</span>
<span id="cb15-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> modprobe dm-mod</span></code></pre></div>
<p>Nun erstellen wir ein <code>LUKS-LVM</code> auf der root-Partition (<code>/dev/sda2</code>):</p>
<div class="sourceCode" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb16-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> cryptsetup luksFormat <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-v</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-s</span> 512 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-h</span> sha512 /dev/sda2</span></code></pre></div>
<p>Hier geben wir unser gewünschtes Passwort ein <strong>und merken es uns!!!</strong>. Wenn ihr das Passwort vergesst, kommt ihr nicht mehr an eure Daten!!!</p>
<p>Jetzt können wir das Laufwerk mounten</p>
<div class="sourceCode" id="cb17" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb17-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> cryptsetup open /dev/sda2 luks_lvm</span></code></pre></div>
<p>(hier muss das Passwort eingegeben werden, welches wir soeben für die Partition erzeugt haben)</p>
<section id="volume-setup" class="level3">
<h3 class="anchored" data-anchor-id="volume-setup">Volume Setup</h3>
<p>Zunächst erstellen wir ein Volume und eine Volume-Gruppe</p>
<div class="sourceCode" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb18-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> pvcreate /dev/mapper/luks_lvm</span>
<span id="cb18-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> vgcreate arch /dev/mapper/luks_lvm</span></code></pre></div>
<p>Wir benötigen auch ein SWAP-Volume. Als Faustregel gilt: RAM-Größe plus 2GB. Mein Laptop hat zB 8GB RAM, daher erstellen wir 10GB Swap mittels</p>
<div class="sourceCode" id="cb19" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb19-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> lvcreate <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-n</span> swap <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-L</span> 10G arch</span></code></pre></div>
<p>Den Rest der Platte verwenden wir für unser Arch-System</p>
<div class="sourceCode" id="cb20" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb20-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> lvcreate <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-n</span> root <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-l</span> +100%FREE arch</span></code></pre></div>
</section>
</section>
<section id="filesystems" class="level2">
<h2 class="anchored" data-anchor-id="filesystems">Filesystems</h2>
<p>Nun müssen die Partitionen formatiert werden.</p>
<p>Die EFI-Partition benötigt das Format <code>FAT32</code>:</p>
<div class="sourceCode" id="cb21" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb21-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> mkfs.fat <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-F32</span> /dev/sda1 </span></code></pre></div>
<p>Für die verschlüsselte root-Partition können wir z.B. <code>btrfs</code> oder <code>ext4</code> verwenden. Ich persönlich begnüge mich mit <code>ext4</code>.</p>
<div class="sourceCode" id="cb22" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb22-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> mkfs.btrfs <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-L</span> root /dev/mapper/arch-root</span>
<span id="cb22-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># oder</span></span>
<span id="cb22-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> mkfs.ext4 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-L</span> root /dev/mapper/arch-root</span></code></pre></div>
<p>Nun formatieren wir noch unseren Swap:</p>
<div class="sourceCode" id="cb23" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb23-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> mkswap /dev/mapper/arch-swap</span></code></pre></div>
</section>
<section id="mounten" class="level2">
<h2 class="anchored" data-anchor-id="mounten">Mounten</h2>
<p>Zuerst mounten und aktivieren wir die SWAP-Partition</p>
<div class="sourceCode" id="cb24" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb24-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> swapon /dev/mapper/arch-swap</span>
<span id="cb24-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> swapon <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-a</span></span></code></pre></div>
<p>Anschließend mounten wir die root-Partition nach <code>/mnt</code>:</p>
<div class="sourceCode" id="cb25" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb25-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> mount /dev/mapper/arch-root /mnt</span></code></pre></div>
<p>Unterhalb von <code>/mnt</code> erstellen wir das <code>/boot</code>-Verzeichnis:</p>
<div class="sourceCode" id="cb26" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb26-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mkdir</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-p</span> /mnt/boot</span></code></pre></div>
<p>Hierhin mounten wir die erzeugte <code>boot</code> Partiton (<code>/dev/sda1</code>)</p>
<div class="sourceCode" id="cb27" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb27-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> mount /dev/sda1 /mnt/boot</span></code></pre></div>
</section>
<section id="installiere-archlinux" class="level2">
<h2 class="anchored" data-anchor-id="installiere-archlinux">Installiere ArchLinux</h2>
<p>Nun ist es endlich an der Zeit gekommen, Archlinux zu installieren. Dieser Befehl bringt die essentiellen Pakete auf die neue Platte:</p>
<div class="sourceCode" id="cb28" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb28-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> pacstrap <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-K</span> /mnt base base-devel linux linux-firmware nano openssh</span></code></pre></div>
<p>Wir erzeugen die <code>fstab</code>-Datei für unser neues System mittels:</p>
<div class="sourceCode" id="cb29" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb29-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> genfstab <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-U</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-p</span> /mnt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> /mnt/etc/fstab</span></code></pre></div>
<section id="chroot-in-die-installation" class="level3">
<h3 class="anchored" data-anchor-id="chroot-in-die-installation">chroot in die Installation</h3>
<p>Wir wechseln in unser neues System mittels:</p>
<div class="sourceCode" id="cb30" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb30-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> arch-chroot /mnt /bin/bash</span></code></pre></div>
<p>Hier können wir nun die grundlegenden Konfigurationen vornehmen.</p>
</section>
</section>
<section id="konfiguration" class="level2">
<h2 class="anchored" data-anchor-id="konfiguration">Konfiguration</h2>
<section id="entschlüssele-die-laufwerke" class="level3">
<h3 class="anchored" data-anchor-id="entschlüssele-die-laufwerke">entschlüssele die Laufwerke</h3>
<p>Damit Linux unsere Partition entschlüsseln kann, müssen wir die Datei <code>mkinitcpio.conf</code> anpassen.</p>
<p>Öffne <code>mkinitcpio.conf</code></p>
<div class="sourceCode" id="cb31" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb31-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> nano /etc/mkinitcpio.conf</span></code></pre></div>
<p>und füge <code>encrypt lvm2</code> zwischen die Hooks <code>block</code> und <code>filesystem</code> ein. Das sieht dann in etwa so aus:</p>
<div class="sourceCode" id="cb32" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb32-1"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">HOOKS</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">(</span>... block encrypt lvm2 filesystems fsck<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">)</span></span></code></pre></div>
<p>Wir müssen gleich noch weitere Änderungen an der Datei vornehmen, aber zunächst installieren wir den Volumemanager <code>lvm2</code></p>
<div class="sourceCode" id="cb33" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb33-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> pacman <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-S</span> lvm2</span></code></pre></div>
</section>
<section id="bootloader" class="level3">
<h3 class="anchored" data-anchor-id="bootloader">Bootloader</h3>
<p>Wir werden <code>systemd-boot</code> für unser System nutzen. Dafür benötigen wir noch ein paar Pakete:</p>
<div class="sourceCode" id="cb34" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb34-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> pacman <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-S</span> efibootmgr dosfstools gptfdisk</span></code></pre></div>
<p>Zuerst installieren wir den EFI-Booteintrag per:</p>
<div class="sourceCode" id="cb35" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb35-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> bootctl install</span></code></pre></div>
<p>Jetzt müssen wir die UUID unserer verschlüsselten LUKS-Partition herausfinden. Da wir Partition <code>/dev/sda2</code> verschlüsselt haben, erhalten wir dessen UUID per:</p>
<div class="sourceCode" id="cb36" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb36-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> blkid /dev/sda2</span></code></pre></div>
<p>Das sieht dann in etwa so aus:</p>
<div class="sourceCode" id="cb37" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb37-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">/dev/sda2:</span> UUID=<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"272b13c4-ce78-47de-b04c-66210edb977d"</span> TYPE=<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"crypto_LUKS"</span> PARTLABEL=<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Linux LUKS"</span> PARTUUID=<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"6b6b86e4-b8fe-4b7d-874d-96c67075b90c"</span></span></code></pre></div>
<p>Die UUID lautet in unserem Beispiel also <code>272b13c4-ce78-47de-b04c-66210edb977d</code>.</p>
<p>Mit diesem Wissen können wir die Datei <code>/boot/loader/entries/arch-uefi.conf</code> mit folgendem Inhalt erstellen:</p>
<div class="sourceCode" id="cb38" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb38-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> nano /boot/loader/entries/arch-uefi.conf</span></code></pre></div>
<div class="sourceCode" id="cb39" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb39-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">title</span>    Arch Linux</span>
<span id="cb39-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">linux</span>    /vmlinuz-linux</span>
<span id="cb39-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">initrd</span>   /initramfs-linux.img</span>
<span id="cb39-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">options</span>  root=/dev/mapper/arch-root cryptdevice=UUID=<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>uuid<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span>:luks_lvm  locale=de_DE.UTF-8</span></code></pre></div>
<p>In unserem Beispiel ändert sich die letzte Zeile in</p>
<div class="sourceCode" id="cb40" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb40-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">options</span>  root=/dev/mapper/arch-root cryptdevice=UUID=272b13c4-ce78-47de-b04c-66210edb977d:luks_lvm  locale=de_DE.UTF-8</span></code></pre></div>
<p>Nun bearbeiten wir die Datei <code>/boot/loader/loader.conf</code> so, dass automatisch in unser Archsystem gebootet wird:</p>
<div class="sourceCode" id="cb41" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb41-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> nano /boot/loader/loader.conf</span></code></pre></div>
<div class="sourceCode" id="cb42" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb42-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">default</span>   arch-uefi</span>
<span id="cb42-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">timeout</span>   1</span></code></pre></div>
</section>
<section id="keyfile" class="level3">
<h3 class="anchored" data-anchor-id="keyfile">Keyfile</h3>
<p>Optional können wir noch Keyfiles erstellen. Hierfür erzeugen wir ein eigenes Verzeichnis:</p>
<div class="sourceCode" id="cb43" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb43-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> mkdir /secure</span></code></pre></div>
<p>…und erstelle ein Keyfile für unserer root-Partition.</p>
<div class="sourceCode" id="cb44" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb44-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> dd if=/dev/random of=/secure/root_keyfile.bin bs=512 count=8</span></code></pre></div>
<p>Anschließend muss die Berechtigung geändert werden:</p>
<div class="sourceCode" id="cb45" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb45-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> chmod 000 /secure/<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">*</span></span></code></pre></div>
<p>Jetzt können wir den Keyfile der Partition zuweisen:</p>
<div class="sourceCode" id="cb46" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb46-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> cryptsetup luksAddKey /dev/sda2 /secure/root_keyfile.bin</span></code></pre></div>
<p>(hier muss wieder das Passwort eingegeben werden, welches wir für die Partition erzeugt haben)</p>
<p>Den Schlüssel müssen wir noch für Linux bekanntmachen:</p>
<div class="sourceCode" id="cb47" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb47-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> nano /etc/mkinitcpio.conf</span></code></pre></div>
<p>Unter <code>FILES</code> fügen wir den Pfad auf den Keyfile hinzu:</p>
<div class="sourceCode" id="cb48" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb48-1"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">FILES</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">(</span>/secure/root_keyfile.bin<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">)</span></span></code></pre></div>
<p>…und erstellen Linux neu:</p>
<div class="sourceCode" id="cb49" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb49-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> mkinitcpio <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-p</span> linux</span></code></pre></div>
</section>
</section>
<section id="systemkonfiguration" class="level2">
<h2 class="anchored" data-anchor-id="systemkonfiguration">Systemkonfiguration</h2>
<p>Zeit für ein paar weitere Systemkonfigurationen.</p>
<section id="timezone" class="level4">
<h4 class="anchored" data-anchor-id="timezone">Timezone</h4>
<p>Unsere Zeitzone ist <code>Europe/Berlin</code>.</p>
<div class="sourceCode" id="cb50" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb50-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> ln <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-sf</span> /usr/share/zoneinfo/Europe/Berlin /etc/localtime</span></code></pre></div>
</section>
<section id="ntp" class="level4">
<h4 class="anchored" data-anchor-id="ntp">NTP</h4>
<p>Mittels <code>NTP</code> holen wir uns die aktuelle Zeit aus dem Netz</p>
<div class="sourceCode" id="cb51" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb51-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> nano /etc/systemd/timesyncd.conf</span></code></pre></div>
<p>Folgende NTP Server können wir verwenden.</p>
<div class="sourceCode" id="cb52" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb52-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">[Time]</span></span>
<span id="cb52-2"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">NTP</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>0.arch.pool.ntp.org <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">1.arch.pool.ntp.org</span> 2.arch.pool.ntp.org 3.arch.pool.ntp.org </span>
<span id="cb52-3"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">FallbackNTP</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>0.pool.ntp.org <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">1.pool.ntp.org</span></span></code></pre></div>
<p>Jetzt kann <code>NTP</code> aktiviert werden</p>
<div class="sourceCode" id="cb53" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb53-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> systemctl enable systemd-timesyncd.service</span></code></pre></div>
</section>
<section id="locale" class="level3">
<h3 class="anchored" data-anchor-id="locale">Locale</h3>
<p>Wir stellen die Sprache auf “deutsch”. Hierfür öffnen wir <code>/etc/locale.gen</code></p>
<div class="sourceCode" id="cb54" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb54-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> nano /etc/locale.gen</span></code></pre></div>
<p>und kommentieren die Zeile mit <code>de_DE.utf8</code> aus.</p>
<div class="sourceCode" id="cb55" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb55-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#de_CH ISO-8859-1</span></span>
<span id="cb55-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">de_DE.UTF-8</span> UTF-8</span>
<span id="cb55-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#de_DE ISO-8859-1</span></span>
<span id="cb55-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#de_DE@euro ISO-8859-15</span></span></code></pre></div>
<p>Jetzt erzeugen wir alle lokalen Sprachdateien</p>
<div class="sourceCode" id="cb56" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb56-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> locale-gen</span></code></pre></div>
<p>…und schreiben es auch noch in <code>/etc/locale.conf</code></p>
<div class="sourceCode" id="cb57" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb57-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> nano /etc/locale.conf</span></code></pre></div>
<div class="sourceCode" id="cb58" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb58-1"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">LANG</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>de_DE.UTF-8</span></code></pre></div>
</section>
<section id="virtuelle-und-tty-konsolen" class="level3">
<h3 class="anchored" data-anchor-id="virtuelle-und-tty-konsolen">virtuelle und TTY Konsolen</h3>
<p>Damit auch die virtuellen Tastaturen auf deutsch eingestellt sind, gebe ich noch ein:</p>
<div class="sourceCode" id="cb59" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb59-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> echo KEYMAP=de-latin1-nodeadkeys <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> /etc/vconsole.conf</span>
<span id="cb59-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> localectl <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--no-convert</span> set-x11-keymap de pc105 deadgraveacute</span>
<span id="cb59-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> localectl <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--no-convert</span> set-keymap de-latin1-nodeadkeys</span></code></pre></div>
<p>Wir können die Einstellungen noch überprüfen mit</p>
<div class="sourceCode" id="cb60" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb60-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> localectl status</span></code></pre></div>
<p>Die Ausgabe sollte so aussehen:</p>
<div class="sourceCode" id="cb61" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb61-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">System</span> Locale: LANG=de_DE.UTF-8</span>
<span id="cb61-2">    <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">VC</span> Keymap: de-latin1-nodeadkeys</span>
<span id="cb61-3">   <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">X11</span> Layout: de</span>
<span id="cb61-4">    <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">X11</span> Model: pc105</span>
<span id="cb61-5">  <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">X11</span> Variant: deadgraveacute</span></code></pre></div>
<p>Beim nächsten Neustart ist das Tastaturlayout auch für TTY auf deutsch.</p>
</section>
<section id="hostname" class="level3">
<h3 class="anchored" data-anchor-id="hostname">Hostname</h3>
<p>Mein Laptop soll “Norbert” heissen.</p>
<div class="sourceCode" id="cb62" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb62-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> echo <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Norbert"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> /etc/hostname</span></code></pre></div>
</section>
<section id="users" class="level3">
<h3 class="anchored" data-anchor-id="users">Users</h3>
<p>Bislang waren wir als <code>root</code> unterwegs. Erzeugen wir uns also einen neuen Benutzer “produnis” mit <code>sudo</code>-Rechten</p>
<div class="sourceCode" id="cb63" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb63-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> useradd <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-m</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-G</span> wheel <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-s</span> /bin/bash produnis</span></code></pre></div>
<p>und vergeben ein Passwort für diesen User mittels</p>
<div class="sourceCode" id="cb64" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb64-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> passwd produnis</span></code></pre></div>
<p>Damit “produnis” <code>sudo</code>-Rechte bekommt, führen wir folgenden Befehl aus</p>
<div class="sourceCode" id="cb65" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb65-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> EDITOR=nano visudo</span></code></pre></div>
<p>und kommentieren die folgende Zeile aus:</p>
<div class="sourceCode" id="cb66" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb66-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">%wheel</span> ALL=<span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ALL:ALL</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ALL</span></span></code></pre></div>
<p>Damit unsere sudo-Befehle nicht aus-timen, kann am Ende der Datei noch hinzugefügt werden:</p>
<div class="sourceCode" id="cb67" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb67-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Defaults</span> passwd_timeout=0</span></code></pre></div>
</section>
<section id="netzwerk" class="level3">
<h3 class="anchored" data-anchor-id="netzwerk">Netzwerk</h3>
<p>Damit wir beim Neustart Netzwerk haben, installieren und aktivieren wir den Networkmanager.</p>
<div class="sourceCode" id="cb68" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb68-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> pacman <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-S</span> networkmanager</span>
<span id="cb68-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> systemctl enable NetworkManager</span></code></pre></div>
<p>Damit auch <code>ssh</code> funktioniert, ergänzen wir</p>
<div class="sourceCode" id="cb69" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb69-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> systemctl enable sshd</span></code></pre></div>
</section>
<section id="microcode" class="level3">
<h3 class="anchored" data-anchor-id="microcode">Microcode</h3>
<p>Es wird empfohlen, die Micorcodes entsprechend eurer CPU zu installieren.</p>
<div class="sourceCode" id="cb70" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb70-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Für AMD</span></span>
<span id="cb70-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> pacman <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-S</span> amd-ucode</span>
<span id="cb70-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ODER</span></span>
<span id="cb70-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Für Intel</span></span>
<span id="cb70-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> pacman <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-S</span> intel-ucode</span></code></pre></div>
</section>
<section id="desktop" class="level3">
<h3 class="anchored" data-anchor-id="desktop">Desktop</h3>
<p>An dieser Stelle sind wir eigentlich schon fertig und können zum ersten Mal neustarten. Ich installiere aber noch einen Desktop und Login-Manager, damit ich direkt auf einer graphischen Oberfläche loslegen kann. Ich selbst verwende am liebsten KDE (also Plasma) mit Wayland (ihr könnt aber auch <a href="https://wiki.archlinux.org/title/GNOME">GNOME</a> oder <a href="https://wiki.archlinux.org/title/Xfce">XFCE</a> installieren). Für eine minimale Installation wähle ich</p>
<div class="sourceCode" id="cb71" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb71-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> pacman <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-S</span> plasma-desktop plasma-wayland-session  kde-applications  sddm sddm-kcm plasma-nm</span></code></pre></div>
<p>Ich bestätige immmer die Vorauswahl, falls Pacman fragt.</p>
<p>Zum Schluss aktiviere ich noch den Loginmanager <code>sddm</code></p>
<div class="sourceCode" id="cb72" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb72-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> systemctl enable sddm</span></code></pre></div>
<p>Fertig, Zeit für einen Reboot.</p>
</section>
</section>
<section id="reboot" class="level2">
<h2 class="anchored" data-anchor-id="reboot">Reboot</h2>
<p>Zunächst verlassen wir die chroot-Umgebung und unmounten die Partitionen.</p>
<div class="sourceCode" id="cb73" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb73-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> exit</span>
<span id="cb73-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> umount <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-R</span> /mnt</span>
<span id="cb73-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> reboot now</span></code></pre></div>
<p>Bei mir meldet sich nach dem Start nun das UEFI-Bootmenu, welches nach 2 Sekunden Archlinux bootet. Hier werde ich nach dem Verschlüsslungspasswort gefragt. Anschließend meldet sich der <code>sddm</code>-Loginbildschirm, und ich kann meine Plasmasession starten.</p>
</section>
<section id="deutsches-tastaturlayout" class="level2">
<h2 class="anchored" data-anchor-id="deutsches-tastaturlayout">Deutsches Tastaturlayout</h2>
<p>Noch ist die KDE-Tastatur nicht auf deutsch eingestellt. Hierfür geht ihr in die Systemeinstellungen, und wählt unter “Tastaur” den Reiter “Belegungen”.</p>
<p><img src="https://www.produnis.de/blog/posts/2024-02-09-ArchLinux-installieren/TastaturDeutsch.webp" class="img-fluid"></p>
<p>Setzt den Haken bei “Belegungen einrichten” und fügt “Deutsch” hinzu. Sobald ihr unten auf “Anwenden” klickt, ist die Tastatur auf deutsches Layout eingestellt.</p>
</section>
<section id="what-if" class="level2">
<h2 class="anchored" data-anchor-id="what-if">…what if?</h2>
<p>Falls doch etwas schief laufen sollte, und ihr z.B. nicht ins System booten könnt, stellt ihr wie folgt wieder die chroot-Umgebung her:</p>
<ul>
<li>boote vom USB-Stick, so wie oben beschrieben</li>
<li><code>cryptsetup open /dev/sda2 luks_lvm</code></li>
<li><code>mount /dev/mapper/arch-root /mnt</code></li>
<li><code>mount /dev/sda1 /mnt/boot</code></li>
<li><code>arch-chroot /mnt /bin/bash</code></li>
</ul>
<p>Jetzt liegt es aber an euch, den Fehler zu finden… ;)</p>
</section>
<section id="weblinks" class="level2">
<h2 class="anchored" data-anchor-id="weblinks">Weblinks</h2>
<ul>
<li><a href="https://wiki.archlinux.de/title/Anleitung_f%C3%BCr_Einsteiger" class="uri">https://wiki.archlinux.de/title/Anleitung_f%C3%BCr_Einsteiger</a></li>
<li><a href="https://github.com/dreamsofautonomy/arch-from-scratch" class="uri">https://github.com/dreamsofautonomy/arch-from-scratch</a></li>
<li><a href="https://www.youtube.com/watch?v=YC7NMbl4goo" class="uri">https://www.youtube.com/watch?v=YC7NMbl4goo</a></li>
</ul>
            <br><center>
            <div class="matrixfoot" id="matrixfooter">
            <a href="https://matrix.to/#/#produnis-blog:tchncs.de">
            <img src="https://www.produnis.de/images/Matrix.webp" width="60">
            </a>
            Diskussion per Matrix unter <a href="https://matrix.to/#/#produnis-blog:tchncs.de">https://matrix.to/#/#produnis-blog:tchncs.de</a>
            </div>
            </center><br>&nbsp;
        


</section>

 ]]></description>
  <category>Arch</category>
  <category>ubuntuusers</category>
  <guid>https://www.produnis.de/blog/posts/2024-02-09-ArchLinux-installieren/</guid>
  <pubDate>Thu, 08 Feb 2024 23:00:00 GMT</pubDate>
  <media:content url="https://www.produnis.de/blog/posts/2024-02-09-ArchLinux-installieren/Arch-Linux-Boot-Screen-1.webp" medium="image" type="image/webp"/>
</item>
<item>
  <title>systemd.service zu bestimmten Zeiten starten und stoppen</title>
  <dc:creator>Joe Slam</dc:creator>
  <link>https://www.produnis.de/blog/posts/2024-01-19-Start-Stop-Systemd-service/</link>
  <description><![CDATA[ 





<p>Ich möchte einen bestimmten <code>systemd</code> Service zu bestimmten Zeiten starten und stoppen. Im Detail geht es um meinen BOINC-Client. Dieser soll von Montag bis Freitag um 17:00 Uhr gestartet, und (ebenfalls von Montag bis Freitag) um 8:00 Uhr morgens gestoppt werden.</p>
<p>Der BOINC-Client bringt bereits seine eigene <code>boinc-client.service</code>-Datei mit, so dass der Dienst mittels <code>systemctl start boinc-client.service</code> und <code>systemctl stop boinc-client.service</code> gestartet und gestoppt werden kann.</p>
<p>Mittels <code>systemd</code> sollen diese Befehle zu den genannten Zeiten ausgeführt werden.</p>
<section id="wrapper-services" class="level2">
<h2 class="anchored" data-anchor-id="wrapper-services">Wrapper-Services</h2>
<p>Ich erstelle mir zwei Hilfs-Services, die jeweils den BOINC-Client starten und stoppen.</p>
<p>FÜr den Starter-Service:</p>
<p><code>sudo nano /etc/systemd/system/start-boinc.service</code></p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">[Unit]</span></span>
<span id="cb1-2"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">Description</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>Start <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">boinc</span> service</span>
<span id="cb1-3"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">After</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>network.target</span>
<span id="cb1-4"></span>
<span id="cb1-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">[Service]</span></span>
<span id="cb1-6"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">Type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>oneshot</span>
<span id="cb1-7"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">ExecStart</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>/usr/bin/systemctl <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">start</span> boinc-client.service</span>
<span id="cb1-8"></span>
<span id="cb1-9"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">[Install]</span></span>
<span id="cb1-10"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">WantedBy</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>multi-user.target</span></code></pre></div>
<p>Für den Stopper-Service:</p>
<p><code>sudo nano /etc/systemd/system/stop-boinc.service</code></p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">[Unit]</span></span>
<span id="cb2-2"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">Description</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>Stop <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">boinc</span> service</span>
<span id="cb2-3"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">After</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>network.target</span>
<span id="cb2-4"></span>
<span id="cb2-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">[Service]</span></span>
<span id="cb2-6"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">Type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>oneshot</span>
<span id="cb2-7"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">ExecStart</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>/usr/bin/systemctl <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">stop</span> boinc-client.service</span>
<span id="cb2-8"></span>
<span id="cb2-9"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">[Install]</span></span>
<span id="cb2-10"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">WantedBy</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>multi-user.target</span></code></pre></div>
</section>
<section id="timer" class="level2">
<h2 class="anchored" data-anchor-id="timer">Timer</h2>
<p>Jetzt brauche ich nur noch zwei Timer, die jeweils die Wrapper-Services auslösen.</p>
<p>Für den Starter:</p>
<p><code>sudo nano /etc/systemd/system/start-boinc.timer</code></p>
<div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb3-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">[Unit]</span></span>
<span id="cb3-2"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">Description</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>Timer <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> starting <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">BOINC</span> client</span>
<span id="cb3-3"></span>
<span id="cb3-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">[Timer]</span></span>
<span id="cb3-5"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">OnCalendar</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>Mon-Fri <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">*-*-*</span> 17:00:00</span>
<span id="cb3-6"></span>
<span id="cb3-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">[Install]</span></span>
<span id="cb3-8"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">WantedBy</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>timers.target</span></code></pre></div>
<p>Für den Stopper:</p>
<p><code>sudo nano /etc/systemd/system/stop-boinc.timer</code></p>
<div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb4-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">[Unit]</span></span>
<span id="cb4-2"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">Description</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>Timer <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> stopping <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">BOINC</span> client</span>
<span id="cb4-3"></span>
<span id="cb4-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">[Timer]</span></span>
<span id="cb4-5"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">OnCalendar</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>Mon-Fri <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">*-*-*</span> 08:00:00</span>
<span id="cb4-6"></span>
<span id="cb4-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">[Install]</span></span>
<span id="cb4-8"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">WantedBy</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>timers.target</span></code></pre></div>
</section>
<section id="timer-aktivieren" class="level2">
<h2 class="anchored" data-anchor-id="timer-aktivieren">Timer aktivieren</h2>
<p>Jetzt müssen die neuen Dateien systemd bekannt gemacht werden:</p>
<p><code>sudo systemctl daemon-reload</code></p>
<p>Anschließend werden die Timer aktiviert.</p>
<p><code>sudo systemctl enable --now start-boinc.timer</code></p>
<p><code>sudo systemctl enable --now stop-boinc.timer</code></p>
<p>Wir können noch überprüfen, ob alles bereit ist.</p>
<p><code>sudo systemctl status start-boinc.timer</code></p>
<p><code>sudo systemctl status stop-boinc.timer</code></p>
<p>Fertig. Mein <code>boinc-client.service</code> wird nun von Montag bis Freitag jeweils um 17:00 Uhr gestartet und um 8:00 Uhr gestoppt.</p>
</section>
<section id="weblinks" class="level2">
<h2 class="anchored" data-anchor-id="weblinks">Weblinks</h2>
<ul>
<li><a href="https://documentation.suse.com/smart/systems-management/html/systemd-working-with-timers/index.html" class="uri">https://documentation.suse.com/smart/systems-management/html/systemd-working-with-timers/index.html</a></li>
<li><a href="https://boinc.bakerlab.org/" class="uri">https://boinc.bakerlab.org/</a></li>
</ul>
            <br><center>
            <div class="matrixfoot" id="matrixfooter">
            <a href="https://matrix.to/#/#produnis-blog:tchncs.de">
            <img src="https://www.produnis.de/images/Matrix.webp" width="60">
            </a>
            Diskussion per Matrix unter <a href="https://matrix.to/#/#produnis-blog:tchncs.de">https://matrix.to/#/#produnis-blog:tchncs.de</a>
            </div>
            </center><br>&nbsp;
        


</section>

 ]]></description>
  <category>systemd</category>
  <category>Jean Pütz</category>
  <category>ubuntuusers</category>
  <guid>https://www.produnis.de/blog/posts/2024-01-19-Start-Stop-Systemd-service/</guid>
  <pubDate>Thu, 18 Jan 2024 23:00:00 GMT</pubDate>
  <media:content url="https://www.produnis.de/images/logos/JeanPuetz.png" medium="image" type="image/png" height="144" width="144"/>
</item>
<item>
  <title>Meine Quarto Extensions</title>
  <dc:creator>Joe Slam</dc:creator>
  <link>https://www.produnis.de/blog/posts/2024-01-16-QuartoExtensions/</link>
  <description><![CDATA[ 





<p>Ich habe die letzten Tage damit verbracht, eigene kleine Extensions für <a href="https://quarto.org">quarto</a> zu schreiben und bei Github zu veröffentlichen. Vielleicht ist ja für den einen oder die andere eine passende Extension dabei…</p>
<section id="quarto-letter" class="level2">
<h2 class="anchored" data-anchor-id="quarto-letter"><a href="https://github.com/produnis/quarto-letter">Quarto Letter</a></h2>
<p>Mit dieser Extension könnt ihr Briefe mittels Quarto erstellen. Vorlage dieser Extension war mein <a href="https://www.produnis.de/blog/posts/2022-09-12-quarto-briefvorlage">Blogeintrag vom 12.09.2022</a>.</p>
<p><img src="https://www.produnis.de/blog/posts/2024-01-16-QuartoExtensions/Testbrief.png" class="img-fluid"></p>
<p>Um die Vorlage zu verwenden tippt ihr ins Terminal:</p>
<p><code>quarto use template produnis/quarto-letter</code></p>
</section>
<section id="quarto-invoice" class="level2">
<h2 class="anchored" data-anchor-id="quarto-invoice"><a href="https://github.com/produnis/quarto-invoice">Quarto Invoice</a></h2>
<p>Diese Extension beruht auf der <code>quarto-letter</code>-Vorlage (s.o.) und erzeugt Rechnungen.</p>
<p><img src="https://www.produnis.de/blog/posts/2024-01-16-QuartoExtensions/invoice.jpg" class="img-fluid"></p>
<p>Um die Vorlage zu verwenden tippt ihr ins Terminal:</p>
<p><code>quarto use template produnis/quarto-invoice</code></p>
</section>
<section id="publikationsliste" class="level2">
<h2 class="anchored" data-anchor-id="publikationsliste"><a href="https://github.com/produnis/publicationlist">Publikationsliste</a></h2>
<p>Diese Extension erzeugt eine Publikationsliste anhand einer BibTeX-Datei. Vorlage für diese Extension war mein <a href="https://www.produnis.de/blog/posts/2021-04-19-publikationsliste-im-lebenslauf-mit-latex/">Blogeintrag vom 19.04.2021</a>.</p>
<p><img src="https://www.produnis.de/blog/posts/2024-01-16-QuartoExtensions/publikationslebenslauf.png" class="img-fluid"></p>
<p>Um die Vorlage zu verwenden tippt ihr ins Terminal:</p>
<p><code>quarto use template produnis/publicationlist</code></p>
</section>
<section id="quarto-cv" class="level2">
<h2 class="anchored" data-anchor-id="quarto-cv"><a href="https://github.com/produnis/quarto-cv">Quarto CV</a></h2>
<p>Diese Extension ist eine Erweiterung der Publikationsliste. Hierbei wird ein hübsches Lebenslaufdokument erstellt, wobei die Möglichkeit besteht, eine (oder mehrere) Publikationslisten hinzuzufügen.</p>
<p><img src="https://www.produnis.de/blog/posts/2024-01-16-QuartoExtensions/lebenslauf.png" class="img-fluid"></p>
<p>Um die Vorlage zu verwenden tippt ihr ins Terminal:</p>
<p><code>quarto use template produnis/quarto-cv</code></p>
</section>
<section id="quarto-timer" class="level2">
<h2 class="anchored" data-anchor-id="quarto-timer"><a href="https://github.com/produnis/quarto-timer">Quarto Timer</a></h2>
<p>Mit dieser Extension lassen sich Countdown-Timer in Folien (oder HTML-Dokumenten) einbauen. Sie beruht auf meinem <a href="https://www.produnis.de/blog/posts/2024-01-04-Revealjs-Timer/">Blogpost vom 04.01.2024</a>.</p>
<p><img src="https://www.produnis.de/blog/posts/2024-01-16-QuartoExtensions/4mintimer.jpg" class="img-fluid"></p>
<p>Ihr könnt den Timer einbinden über:</p>
<p><code>quarto add produnis/quarto-timer</code></p>
</section>
<section id="hsnr-revealjs" class="level2">
<h2 class="anchored" data-anchor-id="hsnr-revealjs"><a href="https://github.com/produnis/hsnr-revealjs">HSNR revealjs</a></h2>
<p>Dies ist meine Vorlage für revealjs-Folien im Design meiner Hochschule (<a href="https://www.hs-niederrhein.de">HSNR</a>). In dieser Extension ist der “<code>Timer</code>” bereits enthalten.</p>
<p>Ihr könnt die Vorlage benutzen über:</p>
<p><code>quarto use template produnis/hsnr-revealjs</code></p>
</section>
<section id="quarto-cert" class="level2">
<h2 class="anchored" data-anchor-id="quarto-cert"><a href="https://github.com/produnis/quarto-cert">Quarto cert</a></h2>
<p>Diese Extension erstellt Teilnehmerzertifikate.</p>
<p><img src="https://www.produnis.de/blog/posts/2024-01-16-QuartoExtensions/zertifikate.webp" class="img-fluid"></p>
<p>Ihr könnt die Vorlage benutzen über:</p>
<p><code>quarto use template produnis/quarto-cert</code></p>
</section>
<section id="quarto-cheatsheet" class="level2">
<h2 class="anchored" data-anchor-id="quarto-cheatsheet"><a href="https://github.com/produnis/quarto-cheatsheet">Quarto Cheatsheet</a></h2>
<p>Mit dieser Extension könnt ihr “Cheatsheets” (Spickzettel) erstellen, zum Beispiel zur Prüfungsvorbereitung oder, um Tastenkombinationen oder git-Befehle zusammenzustellen.</p>
<p><img src="https://www.produnis.de/blog/posts/2024-01-16-QuartoExtensions/quarto-cheatsheet.webp" class="img-fluid"></p>
<p>Ihr könnt die Vorlage benutzen über:</p>
<p><code>quarto use template produnis/quarto-cheatsheet</code></p>
</section>
<section id="weblinks" class="level2">
<h2 class="anchored" data-anchor-id="weblinks">Weblinks</h2>
<ul>
<li><a href="https://github.com/produnis/quarto-letter" class="uri">https://github.com/produnis/quarto-letter</a></li>
<li><a href="https://github.com/produnis/quarto-invoice" class="uri">https://github.com/produnis/quarto-invoice</a></li>
<li><a href="https://github.com/produnis/publicationlist" class="uri">https://github.com/produnis/publicationlist</a></li>
<li><a href="https://github.com/produnis/quarto-cv" class="uri">https://github.com/produnis/quarto-cv</a></li>
<li><a href="https://github.com/produnis/quarto-timer" class="uri">https://github.com/produnis/quarto-timer</a></li>
<li><a href="https://github.com/produnis/hsnr-revealjs" class="uri">https://github.com/produnis/hsnr-revealjs</a></li>
<li><a href="https://github.com/produnis/quarto-cert" class="uri">https://github.com/produnis/quarto-cert</a></li>
<li><a href="https://github.com/produnis/quarto-cheatsheet" class="uri">https://github.com/produnis/quarto-cheatsheet</a></li>
</ul>
            <br><center>
            <div class="matrixfoot" id="matrixfooter">
            <a href="https://matrix.to/#/#produnis-blog:tchncs.de">
            <img src="https://www.produnis.de/images/Matrix.webp" width="60">
            </a>
            Diskussion per Matrix unter <a href="https://matrix.to/#/#produnis-blog:tchncs.de">https://matrix.to/#/#produnis-blog:tchncs.de</a>
            </div>
            </center><br>&nbsp;
        


</section>

 ]]></description>
  <category>quarto</category>
  <category>R</category>
  <category>ubuntuusers</category>
  <guid>https://www.produnis.de/blog/posts/2024-01-16-QuartoExtensions/</guid>
  <pubDate>Mon, 15 Jan 2024 23:00:00 GMT</pubDate>
  <media:content url="https://www.produnis.de/blog/posts/2024-01-16-QuartoExtensions/zertifikate.webp" medium="image" type="image/webp"/>
</item>
</channel>
</rss>
