<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>timmmi</title>
        <link>https://timmmi.de/</link>
        <description>Thoughts, stories and ideas.</description>
        <lastBuildDate>Tue, 23 Jun 2026 21:08:10 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>de</language>
        <image>
            <title>timmmi</title>
            <url>https://timmmi.de/favicon.png</url>
            <link>https://timmmi.de/</link>
        </image>
        <copyright>© 2026 Tim Friedrich - Made with ♥ and SvelteKit;</copyright>
        <atom:link href="https://timmmi.de/rss.xml" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Obsidian als AI Session Log]]></title>
            <link>https://timmmi.de/posts/Obsidian als AI Session Log</link>
            <guid>https://timmmi.de/posts/Obsidian als AI Session Log</guid>
            <pubDate>Sat, 16 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Wie ich Obsidian als Gedächtnis für AI-Sessions nutze und warum ein Agent dadurch nicht jedes Mal bei null anfangen muss.]]></description>
            <content:encoded><![CDATA[<p>Ich nutze AI-Tools inzwischen ziemlich regelmäßig beim Entwickeln. Mal geht es um eine kleine Frage, mal um einen Bug, mal um einen größeren Umbau.</p> <p>Das funktioniert oft erstaunlich gut, aber eine Sache hat mich dabei immer wieder gestört:</p> <p>Die AI vergisst. Also zumindest ab einem gewissen Punkt.</p> <p>Fairerweise passiert das nicht immer sofort. Es hängt stark vom Modell, vom aktuellen Kontext und vom verfügbaren Context Window ab. Aber auch ein großes Context Window ist nicht unbegrenzt und kann je nach Modell schnell teuer werden.</p> <p>Natürlich kann ich in einem Chat weiterarbeiten, solange der Kontext noch da ist. Aber spätestens nach ein paar Tagen, einem neuen Fenster, einem anderen Projekt oder einer zusammengefassten Session ist vieles wieder weg.</p> <p>Was wurde ausprobiert? Welche Entscheidung habe ich getroffen? Warum habe ich diesen einen Workaround genommen und nicht den anderen?</p> <p>Klar, VSCode und andere IDEs haben inzwischen Memories eingebaut und es gibt genug Projekte, die genau dieses Problem lösen wollen. Für mich fehlte trotzdem etwas, das ich selbst lesen, sortieren und bei Bedarf unterwegs anpassen kann.</p> <p>Genau dafür nutze ich inzwischen Obsidian als eine Art Session Log. Quasi etwas, was sich mit Notizen und einem Graphen dafür auskennt:</p> <blockquote><p>Visualize the relationships between your notes. Find hidden patterns in your thinking through a visually engaging and interactive graph. <a href="https://obsidian.md" rel="nofollow">Source</a></p></blockquote> <h2 id="warum-überhaupt-ein-session-log">Warum überhaupt ein Session Log?</h2> <p>Viele Gespräche mit einem AI Agent sind nicht einfach nur “Frage rein, Antwort raus”. Es entsteht nebenbei Kontext:</p> <ul><li><em>Welche</em> <strong>Dateien</strong> geändert wurden</li> <li><em>Welche</em> <strong>Commands</strong> gelaufen sind</li> <li><em>Welche</em> <strong>Fehler</strong> aufgetreten sind</li> <li><em>Welche</em> <strong>Annahmen</strong> falsch waren</li> <li><em>Welche</em> <strong>Idee</strong> zwar gut klang, aber nicht funktioniert hat</li> <li><em>Welche</em> <strong>Folgeaufgaben</strong> offen geblieben sind</li></ul> <p>Das sind alles Dinge, die später wieder nützlich werden können. Nicht nur für mich, sondern auch für den nächsten AI Agent, der in dem Projekt weiterarbeiten soll. Und ich wechsle immer mal die AI Agents oder auch die Provider dafür (aktuell <a href="https://cursor.com" rel="nofollow">Cursor</a>).</p> <p>Statt also alles im Chatverlauf vergammeln zu lassen, speichere ich die wichtigen Teile als Markdown in Obsidian. Das passt gut, weil Obsidian sowieso mein persönliches Notizsystem ist und Markdown einfach kein Spezialformat ist, das in drei Jahren keiner mehr lesen kann. Und so leben dann die Sessions, neben meinen privaten Notizen und unterwegs kann ich so auch die nächste Session beeinflussen.</p> <h2 id="wie-so-eine-session-aussieht">Wie so eine Session aussieht</h2> <p>Am Ende einer längeren Session kann der Agent eine Zusammenfassung in Obsidian speichern. Die ist nicht einfach ein Chatdump, sondern eher ein kleines Arbeitsprotokoll.</p> <p>Bei mir besteht so eine Session typischerweise aus:</p> <div class="mdsvex-shiki shiki shiki-themes catppuccin-mocha" tabindex="0" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4"><div class="header"><span class="language"><svg class="icon" width="16" height="16" viewBox="0 0 576 512" fill="currentColor" aria-hidden="true"><path d="M360.8 1.2c-17-4.9-34.7 5-39.6 22l-128 448c-4.9 17 5 34.7 22 39.6s34.7-5 39.6-22l128-448c4.9-17-5-34.7-22-39.6zm64.6 136.1c-12.5 12.5-12.5 32.8 0 45.3l73.4 73.4-73.4 73.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l96-96c12.5-12.5 12.5-32.8 0-45.3l-96-96c-12.5-12.5-32.8-12.5-45.3 0zm-274.7 0c-12.5-12.5-32.8-12.5-45.3 0l-96 96c-12.5 12.5-12.5 32.8 0 45.3l96 96c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256 150.6 182.6c12.5-12.5 12.5-32.8 0-45.3z"></path></svg>markdown</span><button class="copy" data-code="## Overview

Kurze Zusammenfassung, worum es ging und warum es gemacht wurde.

## Changes

Welche Dateien geändert wurden und was sich fachlich geändert hat.

## Open Points / TODOs

Was noch offen ist oder bewusst nicht erledigt wurde.

## Learnings

Was dabei aufgefallen ist und beim nächsten Mal Zeit sparen kann." type="button" aria-label="Copy code"><svg class="icon copy-icon" width="16" height="16" viewBox="0 0 448 512" fill="currentColor" aria-hidden="true"><path d="M384 336l-192 0c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l133.5 0c4.2 0 8.3 1.7 11.3 4.7l58.5 58.5c3 3 4.7 7.1 4.7 11.3L400 320c0 8.8-7.2 16-16 16zM192 384l192 0c35.3 0 64-28.7 64-64l0-197.5c0-17-6.7-33.3-18.7-45.3L370.7 18.7C358.7 6.7 342.5 0 325.5 0L192 0c-35.3 0-64 28.7-64 64l0 256c0 35.3 28.7 64 64 64zM64 128c-35.3 0-64 28.7-64 64L0 448c0 35.3 28.7 64 64 64l192 0c35.3 0 64-28.7 64-64l0-16-48 0 0 16c0 8.8-7.2 16-16 16L64 464c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l16 0 0-48-16 0z"></path></svg><svg class="icon check-icon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z"></path></svg></button></div><pre class="shiki shiki-themes catppuccin-mocha catppuccin-mocha" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4" tabindex="0"><code><span class="line"><span style="color:#FAB387;--shiki-dark:#FAB387">## Overview</span></span>
<span class="line"></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">Kurze Zusammenfassung, worum es ging und warum es gemacht wurde.</span></span>
<span class="line"></span>
<span class="line"><span style="color:#FAB387;--shiki-dark:#FAB387">## Changes</span></span>
<span class="line"></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">Welche Dateien geändert wurden und was sich fachlich geändert hat.</span></span>
<span class="line"></span>
<span class="line"><span style="color:#FAB387;--shiki-dark:#FAB387">## Open Points / TODOs</span></span>
<span class="line"></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">Was noch offen ist oder bewusst nicht erledigt wurde.</span></span>
<span class="line"></span>
<span class="line"><span style="color:#FAB387;--shiki-dark:#FAB387">## Learnings</span></span>
<span class="line"></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">Was dabei aufgefallen ist und beim nächsten Mal Zeit sparen kann.</span></span></code></pre></div> <p>Das klingt erst einmal banal, ist aber sehr hilfreich. Gerade die Abschnitte “Open Points” und “Learnings” sind Gold wert, weil dort nicht nur das Ergebnis steht, sondern auch der Weg dahin.</p> <h2 id="was-der-agent-damit-machen-kann">Was der Agent damit machen kann</h2> <p>Der spannende Teil ist nicht nur, dass ich nach einer Session eine Notiz habe. Spannend wird es, wenn der Agent diese Notizen wieder nutzen kann.</p> <h3 id="alte-sessions-finden">Alte Sessions finden</h3> <p>Wenn ich ein paar Wochen später wieder an einem Thema arbeite, kann der Agent in meinen alten Sessions suchen. Zum Beispiel nach einem Projektnamen, einem Fehlertext oder einem Tool.</p> <p>Dann muss ich nicht mehr sagen:</p> <blockquote><p>Irgendwann hatten wir doch schon mal dieses Problem mit dem Helm Chart…</p></blockquote> <p>Stattdessen kann der Agent gezielt in den Session Logs suchen, die passenden Einträge laden und mit dem alten Kontext weiterarbeiten.</p> <p>Das ist besonders praktisch bei Problemen, die nicht täglich auftreten. Kubernetes, Renovate, Helm Charts, komische CI-Fehler - alles Dinge, bei denen man sehr schnell vergisst, welche Sackgasse man letztes Mal schon ausprobiert hat.</p> <h3 id="offene-aufgaben-behalten">Offene Aufgaben behalten</h3> <p>Nicht jede AI-Session endet sauber mit “fertig”. Manchmal findet man währenddessen Dinge, die später erledigt werden müssen:</p> <ul><li>einen Follow-up-Bug</li> <li>eine Rechercheaufgabe</li> <li>eine technische Schuld</li> <li>eine Idee für einen weiteren Blogpost</li> <li>einen Test, der noch fehlt</li> <li><em>… oder man hat einfach etwas anderes dazwischen gehabt und aus Versehen die Session gelöscht…</em></li></ul> <p>Dafür kann der Agent eigene Session Tasks anlegen. Das sind keine Projekt-Tickets im klassischen Sinne, sondern eher Aufgaben für die AI selbst. Also: “Wenn wir hier weitermachen, vergiss bitte nicht, vorher X zu prüfen.”</p> <p>Das gefällt mir deutlich besser, als solche Hinweise irgendwo im Chat zu verlieren.</p> <h3 id="projektkontext-herstellen">Projektkontext herstellen</h3> <p>Der Agent kann sich zum Start einer Arbeit einen Überblick holen: Welche Projekte gibt es? Welche Session Tasks sind offen? Was wurde zuletzt gemacht?</p> <blockquote><p>… und ja manchmal schummel’ ich da eine Aufgabe einfach dazwischen und der AI Agent weiß sofort worum es jetzt gehen wird…</p></blockquote> <p>Das ist für mich einer der größten Vorteile. Normalerweise startet ein AI Chat sehr kalt. Ich muss erst wieder erklären, was das Projekt macht, welche Konventionen gelten und warum bestimmte Dinge so sind, wie sie sind.
Klar, man könnte dafür auch <strong>Rules</strong>, Skills und spezielle <strong>Agent Prompts</strong> nutzen, aber so habe ich halt meine wichtigen Rules und Skills in meinem persönlichen Notizprogramm und kann sie schnell ändern.</p> <p>Mit den gespeicherten Sessions kann der Agent zumindest einen Teil dieses Kontextes selbst rekonstruieren.</p> <p>Natürlich ersetzt das kein sauberes <code>README</code>, keine Tests und keine Projektstruktur. Aber es ergänzt sie um etwas, das in Repositories oft fehlt: die Geschichte hinter den Entscheidungen.</p> <h3 id="snippets-wiederverwenden">Snippets wiederverwenden</h3> <p>Neben Sessions kann der Agent auch kleine Snippets in Obsidian ablegen. Also zum Beispiel einen nützlichen Shell-Befehl, ein Jsonnet-Beispiel oder eine kleine SQL-Abfrage.</p> <p>Das ist praktisch, weil viele dieser Dinge nicht direkt in ein Projekt gehören, aber trotzdem wiederverwendbar sind. So entsteht mit der Zeit eine kleine persönliche Wissensdatenbank, die nicht nur für mich, sondern auch für die AI durchsuchbar ist.</p> <h2 id="warum-obsidian">Warum Obsidian?</h2> <p>Ich hätte dafür natürlich auch irgendeine Datenbank, ein Wiki oder ein spezielles Agent-Memory-Tool nehmen können. Aber Obsidian hat für mich ein paar klare Vorteile:</p> <ul><li>Es ist einfach Markdown.</li> <li>Ich kann alles selbst lesen und bearbeiten.</li> <li>Die Daten liegen bei mir.</li> <li>Notizen lassen sich verlinken.</li> <li>Und es hat bereits eine Graph Funktion um Verlinkungen untereinander darzustellen</li> <li>Es funktioniert auch ohne AI.</li></ul> <p>Gerade der letzte Punkt ist mir wichtig. Ich möchte kein System bauen, das nur dann nützlich ist, wenn ein bestimmtes Tool gerade funktioniert. Wenn der Agent Mist baut oder das Tool morgen verschwindet, bleiben die Notizen trotzdem brauchbar. Zusätzlich kann ich es unterwegs anpassen und verfeinern. Die wichtigsten Ideen kommen doch auf einer langen Bahnfahrt ohne Internet.</p> <h2 id="welche-plugins-ich-dafür-nutze">Welche Plugins ich dafür nutze</h2> <p>Obsidian funktioniert schon ohne Plugins sehr gut, aber für diesen Workflow habe ich mir ein paar Erweiterungen installiert, damit es im Alltag nicht nur technisch funktioniert, sondern sich auch gut anfühlt.</p> <p><a href="https://community.obsidian.md/plugins/base-board" rel="nofollow">Base Board</a> nutze ich, um meine Session Tasks als Kanban anzuzeigen. Die Aufgaben liegen weiterhin als Markdown-Dateien mit Frontmatter im Vault, aber ich kann sie visuell zwischen Spalten verschieben. Genau das ist für AI-Follow-ups praktisch: Aus “das sollten wir später noch prüfen” wird eine sichtbare Karte, die nicht im Chat verschwindet.</p> <p><a href="https://community.obsidian.md/plugins/notebook-navigator" rel="nofollow">Notebook Navigator</a> sorgt dafür, dass alles hübsch und organisiert aussieht. Der normale Datei-Browser von Obsidian ist okay, aber Notebook Navigator erinnert mich an das Beste von Bear: eine klare Seitenleiste, schnelle Orientierung und ein Schreibgefühl, bei dem man nicht ständig das Gefühl hat, in einem Dateisystem herumzuklicken.</p> <p>Und weil am Ende doch nichts über ein gutes Theme geht, nutze ich <a href="https://community.obsidian.md/plugins/obsidian-minimal-settings" rel="nofollow">Minimal Theme Settings</a>. Das ist kein Muss für den AI-Workflow, aber wenn ich jeden Tag in einem Tool arbeite, möchte ich auch gerne hineinschauen. Gute Typografie und ein ruhiges Theme machen für mich mehr aus, als man zuerst denkt.</p> <h2 id="warum-selbst-gebaut">Warum selbst gebaut?</h2> <p>Die Verbindung zwischen AI Agent und Obsidian läuft bei mir über einen eigenen MCP. Den habe ich nicht komplett von Hand geschrieben, sondern mir mithilfe von AI bauen lassen.</p> <p>Das klingt im ersten Moment vielleicht etwas rekursiv, passt aber ziemlich gut: Die AI weiß am besten, wie sie ein Tool benutzen möchte. Welche Parameter hilfreich sind, welche Aktionen häufig gebraucht werden und welche Struktur eine Session haben sollte, merkt man sehr schnell, wenn man den Agent damit arbeiten lässt.</p> <p>Natürlich hätte ich auch eine etablierte Lösung nehmen können. Aber dann wäre ich wieder an deren Logik und Arbeitsweise gebunden. Ich wollte etwas haben, das ich für meinen eigenen Workflow weiterentwickeln kann. Wenn mir auffällt, dass eine Funktion fehlt, kann ich sie ergänzen. Wenn ein Tool unnötige Roundtrips erzeugt, kann ich es umbauen. Wenn die Session Logs eine bessere Struktur brauchen, ändere ich genau das.</p> <p>Für mich ist das also weniger ein fertiges Produkt und mehr ein kleines Werkzeug, das mit meinem Arbeitsstil mitwächst.</p> <h2 id="wo-ich-vorsichtig-bin">Wo ich vorsichtig bin</h2> <p>So ein Session Log ist kein magisches Gedächtnis. Man muss trotzdem aufpassen, was gespeichert wird.</p> <p>Secrets, Tokens oder private Daten gehören dort nicht rein. Auch komplette Chatverläufe speichere ich nicht blind. Für mich funktioniert es besser, wenn die AI am Ende eine strukturierte Zusammenfassung schreibt und ich im Zweifel noch einmal drüber schaue.</p> <p>Außerdem sollte man den gespeicherten Kontext nicht als Wahrheit behandeln. Nur weil in einer alten Session steht, dass etwas ein guter Ansatz war, heißt das nicht, dass es heute noch stimmt. Versionen ändern sich, Projekte ändern sich und manchmal war die alte Annahme einfach falsch. Aber genau dafür passt Obsidian super, ich ändere das einfach in einem Tool, wo ich Markdown nur als Hilfsmittel nehme.</p> <h2 id="mein-fazit">Mein Fazit</h2> <p>Obsidian als AI Session Log ist für mich ein ziemlich pragmatischer Ansatz. Kein großes Framework, kein kompliziertes Setup, sondern einfach Markdown-Dateien mit brauchbarer Struktur.</p> <p>Der größte Vorteil ist, dass AI-Arbeit dadurch weniger flüchtig wird. Erkenntnisse verschwinden nicht im Chatverlauf, offene Punkte bleiben sichtbar und der nächste Agent kann sich schneller wieder einarbeiten.</p> <p>Oder anders gesagt: Ich gebe der AI kein perfektes Gedächtnis, aber wenigstens ein Notizbuch.</p>]]></content:encoded>
            <enclosure url="https://timmmi.de/images/jan-kahanek-g3O5ZtRk2E4-unsplash.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Bookmarks: Januar 2026]]></title>
            <link>https://timmmi.de/posts/bookmarks_januar_2026</link>
            <guid>https://timmmi.de/posts/bookmarks_januar_2026</guid>
            <pubDate>Sat, 24 Jan 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Was sich diesen Monat so in meinen Browser-Tabs gestapelt hat – nur das gute Zeug!]]></description>
            <content:encoded><![CDATA[<div class="w-full mx-auto max-w-4xl my-6"><div class="flex flex-col items-center justify-center gap-4 p-8 border border-base-300 rounded-lg bg-base-100"><div class="text-center"><p class="text-sm text-base-content/70">Externer Inhalt von <span class="font-semibold">www.youtube.com</span></p> <p class="text-xs text-base-content/50 mt-1">Durch das Laden werden Daten an Drittanbieter übertragen</p></div> <div class="prose prose-sm max-w-none [&amp;>*:first-child]:mt-0 [&amp;>*:last-child]:mb-0"><!---->AI Slop bezeichnet die Flut an billigem, KI-generiertem Content, der aktuell viele Plattformen überschwemmt. Solar Sands zeigt in diesem Video eindrücklich, warum dies weit mehr als nur ein lästiges Phänomen ist und für Künstler zur existenziellen Bedrohung wird. <p>Erst werden Werke ungefragt als Trainingsdaten abgegriffen, nur um anschließend von genau dieser generierten Masse verdrängt zu werden. Ein sehenswerter Beitrag für alle, die verstehen wollen, warum sich das Internet gerade so <em>seltsam</em> verändert und weshalb Künstler zurecht protestieren.</p> <p>Direkter Link: <a href="https://www.youtube.com/watch?v=_zfN9wnPvU0" rel="nofollow">https://www.youtube.com/watch?v=_zfN9wnPvU0</a></p><!----></div> <button class="btn btn-primary">Inhalt laden</button> <a href="https://www.youtube.com/watch?v=_zfN9wnPvU0" target="_blank" rel="noopener noreferrer" class="link link-primary text-sm">Direkt zur Quelle →</a></div></div><!----> <a href="https://indieblog.page" target="_blank" rel="noopener noreferrer" class="card card-compact bg-base-100 border border-base-300 hover:border-primary/50 hover:shadow-lg transition-all duration-200 group w-full"><div class="card-body"><div class="flex items-start gap-4"><div class="flex-shrink-0 mt-1"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide-icon lucide lucide-bookmark w-5 h-5 text-base-content/60 group-hover:text-primary transition-colors"><!----><path d="M17 3a2 2 0 0 1 2 2v15a1 1 0 0 1-1.496.868l-4.512-2.578a2 2 0 0 0-1.984 0l-4.512 2.578A1 1 0 0 1 5 20V5a2 2 0 0 1 2-2z"><!----></path><!----><!----><!----></svg><!----></div> <div class="flex-1 min-w-0"><h3 class="card-title text-base font-semibold text-base-content group-hover:text-primary transition-colors mb-1">Indie Blog</h3> <p class="text-xs text-base-content/50 mb-2 break-all">https://indieblog.page</p> <div class="prose prose-sm max-w-none [&amp;>*:first-child]:mt-0 [&amp;>*:last-child]:mb-0"><!---->Eine kleine Entdeckungsplattform für das IndieWeb. Per Klick landest du auf einem zufälligen Blogpost aus persönlichen Blogs – fernab von Algorithmen und Tracking. Ideal, um sich *inspirieren* zu lassen oder einfach mal zu sehen, was Menschen noch auf ihren eigenen Websites schreiben.<!----></div></div> <div class="flex-shrink-0 mt-1"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide-icon lucide lucide-chevron-right w-4 h-4 text-base-content/40 group-hover:text-primary group-hover:translate-x-1 transition-all"><!----><path d="m9 18 6-6-6-6"><!----></path><!----><!----><!----></svg><!----></div></div></div></a><!----> <a href="https://www.nibzard.com/agentic-handbook" target="_blank" rel="noopener noreferrer" class="card card-compact bg-base-100 border border-base-300 hover:border-primary/50 hover:shadow-lg transition-all duration-200 group w-full"><div class="card-body"><div class="flex items-start gap-4"><div class="flex-shrink-0 mt-1"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide-icon lucide lucide-bookmark w-5 h-5 text-base-content/60 group-hover:text-primary transition-colors"><!----><path d="M17 3a2 2 0 0 1 2 2v15a1 1 0 0 1-1.496.868l-4.512-2.578a2 2 0 0 0-1.984 0l-4.512 2.578A1 1 0 0 1 5 20V5a2 2 0 0 1 2-2z"><!----></path><!----><!----><!----></svg><!----></div> <div class="flex-1 min-w-0"><h3 class="card-title text-base font-semibold text-base-content group-hover:text-primary transition-colors mb-1">Agentic Handbook</h3> <p class="text-xs text-base-content/50 mb-2 break-all">https://www.nibzard.com/agentic-handbook</p> <div class="prose prose-sm max-w-none [&amp;>*:first-child]:mt-0 [&amp;>*:last-child]:mb-0"><!---->Ein produktionsorientierter Guide für AI Agents, der zeigt, wie man LLMs in Loops mit Tools und State packt – und warum die meisten "Agent-Fails" eigentlich *Loop-Design-Fails* sind. Keine Hype-Versprechen, sondern praktische Patterns: Diff-first Workflows, deterministische Checks und klare Exit-Bedingungen. Hilfreich für alle, die über Copy-Paste-Workflows hinauswollen.<!----></div></div> <div class="flex-shrink-0 mt-1"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide-icon lucide lucide-chevron-right w-4 h-4 text-base-content/40 group-hover:text-primary group-hover:translate-x-1 transition-all"><!----><path d="m9 18 6-6-6-6"><!----></path><!----><!----><!----></svg><!----></div></div></div></a><!----> <a href="https://stadt-bremerhaven.de/google-veroeffentlicht-translategemma-offene-sprachmodelle-fuer-bessere-uebersetzungen/" target="_blank" rel="noopener noreferrer" class="card card-compact bg-base-100 border border-base-300 hover:border-primary/50 hover:shadow-lg transition-all duration-200 group w-full"><div class="card-body"><div class="flex items-start gap-4"><div class="flex-shrink-0 mt-1"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide-icon lucide lucide-bookmark w-5 h-5 text-base-content/60 group-hover:text-primary transition-colors"><!----><path d="M17 3a2 2 0 0 1 2 2v15a1 1 0 0 1-1.496.868l-4.512-2.578a2 2 0 0 0-1.984 0l-4.512 2.578A1 1 0 0 1 5 20V5a2 2 0 0 1 2-2z"><!----></path><!----><!----><!----></svg><!----></div> <div class="flex-1 min-w-0"><h3 class="card-title text-base font-semibold text-base-content group-hover:text-primary transition-colors mb-1">TranslateGemma</h3> <p class="text-xs text-base-content/50 mb-2 break-all">https://stadt-bremerhaven.de/google-veroeffentlicht-translategemma-offene-sprachmodelle-fuer-bessere-uebersetzungen/</p> <div class="prose prose-sm max-w-none [&amp;>*:first-child]:mt-0 [&amp;>*:last-child]:mb-0"><!---->Google hat TranslateGemma veröffentlicht – offene Sprachmodelle speziell für Übersetzungen, auch in Nischensprachen. Die Modelle basieren auf Gemma 2 und nutzen eine Technik namens "Monolingual Knowledge Adaptation", um erst das Sprachgefühl zu stärken, bevor das eigentliche Übersetzen trainiert wird. Verfügbar auf Hugging Face und Kaggle, interessant für Devs, die Übersetzungs-Tools bauen wollen, ohne alles durch Cloud-Dienste zu jagen. Schaue ich mir auf jeden Fall mal an.<!----></div></div> <div class="flex-shrink-0 mt-1"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide-icon lucide lucide-chevron-right w-4 h-4 text-base-content/40 group-hover:text-primary group-hover:translate-x-1 transition-all"><!----><path d="m9 18 6-6-6-6"><!----></path><!----><!----><!----></svg><!----></div></div></div></a><!----> <a href="https://dev.to/himanshu_bhatt/networking-101-6-subnets-cidr-nat-341c" target="_blank" rel="noopener noreferrer" class="card card-compact bg-base-100 border border-base-300 hover:border-primary/50 hover:shadow-lg transition-all duration-200 group w-full"><div class="card-body"><div class="flex items-start gap-4"><div class="flex-shrink-0 mt-1"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide-icon lucide lucide-bookmark w-5 h-5 text-base-content/60 group-hover:text-primary transition-colors"><!----><path d="M17 3a2 2 0 0 1 2 2v15a1 1 0 0 1-1.496.868l-4.512-2.578a2 2 0 0 0-1.984 0l-4.512 2.578A1 1 0 0 1 5 20V5a2 2 0 0 1 2-2z"><!----></path><!----><!----><!----></svg><!----></div> <div class="flex-1 min-w-0"><h3 class="card-title text-base font-semibold text-base-content group-hover:text-primary transition-colors mb-1">Networking 101: Subnets, CIDR, NAT</h3> <p class="text-xs text-base-content/50 mb-2 break-all">https://dev.to/himanshu_bhatt/networking-101-6-subnets-cidr-nat-341c</p> <div class="prose prose-sm max-w-none [&amp;>*:first-child]:mt-0 [&amp;>*:last-child]:mb-0"><!---->Ein Einsteiger-freundlicher Guide zu Netzwerk-Grundlagen für DevOps. Erklärt ohne akademisches Geschwafel, was Subnets sind, wie CIDR funktioniert (`/24` = ~256 IPs, fertig) und warum NAT existiert. Besonders hilfreich, wenn du verstehen willst, warum deine DB im Private Subnet liegt und wie Public/Private Subnets in Cloud-Architekturen zusammenspielen.<!----></div></div> <div class="flex-shrink-0 mt-1"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide-icon lucide lucide-chevron-right w-4 h-4 text-base-content/40 group-hover:text-primary group-hover:translate-x-1 transition-all"><!----><path d="m9 18 6-6-6-6"><!----></path><!----><!----><!----></svg><!----></div></div></div></a><!----> <a href="https://dev.to/devteam/fighting-spam-at-scale-how-we-use-gemini-to-protect-the-dev-community-277j" target="_blank" rel="noopener noreferrer" class="card card-compact bg-base-100 border border-base-300 hover:border-primary/50 hover:shadow-lg transition-all duration-200 group w-full"><div class="card-body"><div class="flex items-start gap-4"><div class="flex-shrink-0 mt-1"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide-icon lucide lucide-bookmark w-5 h-5 text-base-content/60 group-hover:text-primary transition-colors"><!----><path d="M17 3a2 2 0 0 1 2 2v15a1 1 0 0 1-1.496.868l-4.512-2.578a2 2 0 0 0-1.984 0l-4.512 2.578A1 1 0 0 1 5 20V5a2 2 0 0 1 2-2z"><!----></path><!----><!----><!----></svg><!----></div> <div class="flex-1 min-w-0"><h3 class="card-title text-base font-semibold text-base-content group-hover:text-primary transition-colors mb-1">Fighting Spam at Scale</h3> <p class="text-xs text-base-content/50 mb-2 break-all">https://dev.to/devteam/fighting-spam-at-scale-how-we-use-gemini-to-protect-the-dev-community-277j</p> <div class="prose prose-sm max-w-none [&amp;>*:first-child]:mt-0 [&amp;>*:last-child]:mb-0"><!---->Das DEV.to-Team erklärt, wie sie Gemini nutzen, um Spam zu bekämpfen – und zwar *bevor* Moderatoren sich damit rumschlagen müssen. Hybrider Ansatz aus Algorithmen und LLM-Analyse, bei dem User-Context (Account-Alter, Badges, History) in die Bewertung einfließt. Interessanter Einblick, wie man KI für Content-Moderation einsetzt, ohne False Positives zu produzieren.<!----></div></div> <div class="flex-shrink-0 mt-1"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide-icon lucide lucide-chevron-right w-4 h-4 text-base-content/40 group-hover:text-primary group-hover:translate-x-1 transition-all"><!----><path d="m9 18 6-6-6-6"><!----></path><!----><!----><!----></svg><!----></div></div></div></a><!----> <a href="https://selfh.st/post/software-mispronounce/" target="_blank" rel="noopener noreferrer" class="card card-compact bg-base-100 border border-base-300 hover:border-primary/50 hover:shadow-lg transition-all duration-200 group w-full"><div class="card-body"><div class="flex items-start gap-4"><div class="flex-shrink-0 mt-1"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide-icon lucide lucide-bookmark w-5 h-5 text-base-content/60 group-hover:text-primary transition-colors"><!----><path d="M17 3a2 2 0 0 1 2 2v15a1 1 0 0 1-1.496.868l-4.512-2.578a2 2 0 0 0-1.984 0l-4.512 2.578A1 1 0 0 1 5 20V5a2 2 0 0 1 2-2z"><!----></path><!----><!----><!----></svg><!----></div> <div class="flex-1 min-w-0"><h3 class="card-title text-base font-semibold text-base-content group-hover:text-primary transition-colors mb-1">Software You're Mispronouncing</h3> <p class="text-xs text-base-content/50 mb-2 break-all">https://selfh.st/post/software-mispronounce/</p> <div class="prose prose-sm max-w-none [&amp;>*:first-child]:mt-0 [&amp;>*:last-child]:mb-0"><!---->Ein Guide zur korrekten Aussprache von Self-Hosted Software. Wusstest du, dass Forgejo "for-JAY-oh" heißt? Oder Immich wie "image"? Eine liebevoll zusammengestellte Liste mit phonetischen Schreibweisen und Quellen – direkt von den Entwicklern bestätigt. Macht deutlich, wie oft wir uns bei Tool-Namen vertun. Forgejo war auch für mich eine *Überraschung*.<!----></div></div> <div class="flex-shrink-0 mt-1"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide-icon lucide lucide-chevron-right w-4 h-4 text-base-content/40 group-hover:text-primary group-hover:translate-x-1 transition-all"><!----><path d="m9 18 6-6-6-6"><!----></path><!----><!----><!----></svg><!----></div></div></div></a><!----> <h2 id="snippets-des-monats">Snippets des Monats</h2> <p><code>grep -v</code> ist die invertierte Suche: Zeigt alle Zeilen, die <em>nicht</em> das angegebene Pattern enthalten. Praktisch, wenn du Noise aus Logs oder Configs filtern willst – etwa alle Debug-Zeilen rauswerfen oder Kommentare ignorieren. Das <code>-v</code> steht für “invert-match” und gehört zu den nützlichsten Flags, wenn du nicht nach etwas suchst, sondern etwas <em>loswerden</em> willst.</p> <div class="mdsvex-shiki shiki shiki-themes catppuccin-mocha" tabindex="0" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4"><div class="header"><span class="language"><svg class="icon" width="16" height="16" viewBox="0 0 576 512" fill="currentColor" aria-hidden="true"><path d="M360.8 1.2c-17-4.9-34.7 5-39.6 22l-128 448c-4.9 17 5 34.7 22 39.6s34.7-5 39.6-22l128-448c4.9-17-5-34.7-22-39.6zm64.6 136.1c-12.5 12.5-12.5 32.8 0 45.3l73.4 73.4-73.4 73.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l96-96c12.5-12.5 12.5-32.8 0-45.3l-96-96c-12.5-12.5-32.8-12.5-45.3 0zm-274.7 0c-12.5-12.5-32.8-12.5-45.3 0l-96 96c-12.5 12.5-12.5 32.8 0 45.3l96 96c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256 150.6 182.6c12.5-12.5 12.5-32.8 0-45.3z"></path></svg>shell</span><button class="copy" data-code="grep -v &quot;pattern&quot; file" type="button" aria-label="Copy code"><svg class="icon copy-icon" width="16" height="16" viewBox="0 0 448 512" fill="currentColor" aria-hidden="true"><path d="M384 336l-192 0c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l133.5 0c4.2 0 8.3 1.7 11.3 4.7l58.5 58.5c3 3 4.7 7.1 4.7 11.3L400 320c0 8.8-7.2 16-16 16zM192 384l192 0c35.3 0 64-28.7 64-64l0-197.5c0-17-6.7-33.3-18.7-45.3L370.7 18.7C358.7 6.7 342.5 0 325.5 0L192 0c-35.3 0-64 28.7-64 64l0 256c0 35.3 28.7 64 64 64zM64 128c-35.3 0-64 28.7-64 64L0 448c0 35.3 28.7 64 64 64l192 0c35.3 0 64-28.7 64-64l0-16-48 0 0 16c0 8.8-7.2 16-16 16L64 464c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l16 0 0-48-16 0z"></path></svg><svg class="icon check-icon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z"></path></svg></button></div><pre class="shiki shiki-themes catppuccin-mocha catppuccin-mocha" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4" tabindex="0"><code><span class="line"><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic">grep</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> -v</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> "pattern"</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> file</span></span></code></pre></div> <h2 id="technologien-des-monats">Technologien des Monats</h2> <a href="https://betterstack.com/community/guides/scaling-nodejs/drizzle-orm/" target="_blank" rel="noopener noreferrer" class="card card-compact bg-base-100 border border-base-300 hover:border-primary/50 hover:shadow-lg transition-all duration-200 group w-full"><div class="card-body"><div class="flex items-start gap-4"><div class="flex-shrink-0 mt-1"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide-icon lucide lucide-bookmark w-5 h-5 text-base-content/60 group-hover:text-primary transition-colors"><!----><path d="M17 3a2 2 0 0 1 2 2v15a1 1 0 0 1-1.496.868l-4.512-2.578a2 2 0 0 0-1.984 0l-4.512 2.578A1 1 0 0 1 5 20V5a2 2 0 0 1 2-2z"><!----></path><!----><!----><!----></svg><!----></div> <div class="flex-1 min-w-0"><h3 class="card-title text-base font-semibold text-base-content group-hover:text-primary transition-colors mb-1">Drizzle ORM</h3> <p class="text-xs text-base-content/50 mb-2 break-all">https://betterstack.com/community/guides/scaling-nodejs/drizzle-orm/</p> <div class="prose prose-sm max-w-none [&amp;>*:first-child]:mt-0 [&amp;>*:last-child]:mb-0"><!---->Ein TypeScript-first ORM, das sich irgendwo zwischen raw SQL und klassischen ORMs ansiedelt. Du definierst dein Schema in TypeScript, Drizzle generiert automatisch die Types – typsicher, ohne Magie. Unterstützt PostgreSQL, MySQL und SQLite. In SvelteKit nutzt du es typischerweise in `+page.server.ts` oder API-Routes: Schema definieren, `drizzle()`-Instanz erstellen, Queries schreiben. Kein Overhead, kein Boilerplate – einfach SQL mit Type Safety.<!----></div></div> <div class="flex-shrink-0 mt-1"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide-icon lucide lucide-chevron-right w-4 h-4 text-base-content/40 group-hover:text-primary group-hover:translate-x-1 transition-all"><!----><path d="m9 18 6-6-6-6"><!----></path><!----><!----><!----></svg><!----></div></div></div></a><!----> <a href="https://www.better-auth.com" target="_blank" rel="noopener noreferrer" class="card card-compact bg-base-100 border border-base-300 hover:border-primary/50 hover:shadow-lg transition-all duration-200 group w-full"><div class="card-body"><div class="flex items-start gap-4"><div class="flex-shrink-0 mt-1"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide-icon lucide lucide-bookmark w-5 h-5 text-base-content/60 group-hover:text-primary transition-colors"><!----><path d="M17 3a2 2 0 0 1 2 2v15a1 1 0 0 1-1.496.868l-4.512-2.578a2 2 0 0 0-1.984 0l-4.512 2.578A1 1 0 0 1 5 20V5a2 2 0 0 1 2-2z"><!----></path><!----><!----><!----></svg><!----></div> <div class="flex-1 min-w-0"><h3 class="card-title text-base font-semibold text-base-content group-hover:text-primary transition-colors mb-1">Better Auth</h3> <p class="text-xs text-base-content/50 mb-2 break-all">https://www.better-auth.com</p> <div class="prose prose-sm max-w-none [&amp;>*:first-child]:mt-0 [&amp;>*:last-child]:mb-0"><!---->Eine framework-agnostische Auth-Library für TypeScript, die sich als Alternative zu Auth.js positioniert. Unterstützt Email/Password, Social Logins, 2FA, Magic Links – erweiterbar über Plugins. In SvelteKit bindest du den Handler in `hooks.server.ts` ein (`svelteKitHandler`), Session-State läuft über Nano-Stores. Lässt sich direkt mit Drizzle kombinieren. Setup in unter 5 Minuten, kein Config-Hell.<!----></div></div> <div class="flex-shrink-0 mt-1"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide-icon lucide lucide-chevron-right w-4 h-4 text-base-content/40 group-hover:text-primary group-hover:translate-x-1 transition-all"><!----><path d="m9 18 6-6-6-6"><!----></path><!----><!----><!----></svg><!----></div></div></div></a><!---->]]></content:encoded>
            <enclosure url="https://timmmi.de/images/kelsy-gagnebin-jcD8lXN27Xs-unsplash.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Meine Shell Abkürzungen]]></title>
            <link>https://timmmi.de/posts/meine_shell_abkuerzungen</link>
            <guid>https://timmmi.de/posts/meine_shell_abkuerzungen</guid>
            <pubDate>Sat, 26 Apr 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[In meinem privaten und Berufsumfeld bin ich viel im Terminal unterwegs. Nicht weil ich muss, sondern weil ich es so gelernt habe. Aber auch in diesem Umfeld kann man sich vieles erleichtern und unterstützen lassen. Ein Hilfsmittel sind 'alias' im Terminal zu definieren. Hier präsentiere ich meine Abkürzungen.]]></description>
            <content:encoded><![CDATA[<p>In meinem privaten und beruflichen Umfeld arbeite ich häufig mit dem Terminal. Nicht aus Notwendigkeit, sondern weil ich es mir so angewöhnt habe. Doch auch hier gibt es Möglichkeiten, den Arbeitsalltag zu vereinfachen. Eine besonders nützliche Methode sind sogenannte ‘alias’.</p> <p>Dieser Aufruf ermöglicht es, komplexe oder lange Befehle durch kurze, prägnante Abkürzungen zu ersetzen. So kann man effizienter arbeiten und spart wertvolle Zeit bei wiederkehrenden Aufgaben.</p> <div role="alert" class="alert alert-info alert-soft"><span><!---->Ich werde diese Beitrag immer mal wieder aktualisieren und daher in verschieden Einsatzzwecken unterteilen.<!----></span></div><!----> <h2 id="kubernetes">Kubernetes</h2> <p>Immer wieder <code>kubectl</code> zu schreiben, birgt <em>Fehlerpotential</em> und natürlich kostet es <em>Zeit</em>. Daher kürze ich in meinem Terminals ‘kubectl’ immer mit <code>k</code> ab.</p> <div class="mdsvex-shiki shiki shiki-themes catppuccin-mocha" tabindex="0" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4"><div class="header"><span class="language"><svg class="icon" width="16" height="16" viewBox="0 0 576 512" fill="currentColor" aria-hidden="true"><path d="M360.8 1.2c-17-4.9-34.7 5-39.6 22l-128 448c-4.9 17 5 34.7 22 39.6s34.7-5 39.6-22l128-448c4.9-17-5-34.7-22-39.6zm64.6 136.1c-12.5 12.5-12.5 32.8 0 45.3l73.4 73.4-73.4 73.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l96-96c12.5-12.5 12.5-32.8 0-45.3l-96-96c-12.5-12.5-32.8-12.5-45.3 0zm-274.7 0c-12.5-12.5-32.8-12.5-45.3 0l-96 96c-12.5 12.5-12.5 32.8 0 45.3l96 96c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256 150.6 182.6c12.5-12.5 12.5-32.8 0-45.3z"></path></svg>shell</span><button class="copy" data-code="alias k=kubectl" type="button" aria-label="Copy code"><svg class="icon copy-icon" width="16" height="16" viewBox="0 0 448 512" fill="currentColor" aria-hidden="true"><path d="M384 336l-192 0c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l133.5 0c4.2 0 8.3 1.7 11.3 4.7l58.5 58.5c3 3 4.7 7.1 4.7 11.3L400 320c0 8.8-7.2 16-16 16zM192 384l192 0c35.3 0 64-28.7 64-64l0-197.5c0-17-6.7-33.3-18.7-45.3L370.7 18.7C358.7 6.7 342.5 0 325.5 0L192 0c-35.3 0-64 28.7-64 64l0 256c0 35.3 28.7 64 64 64zM64 128c-35.3 0-64 28.7-64 64L0 448c0 35.3 28.7 64 64 64l192 0c35.3 0 64-28.7 64-64l0-16-48 0 0 16c0 8.8-7.2 16-16 16L64 464c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l16 0 0-48-16 0z"></path></svg><svg class="icon check-icon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z"></path></svg></button></div><pre class="shiki shiki-themes catppuccin-mocha catppuccin-mocha" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4" tabindex="0"><code><span class="line"><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">alias</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> k</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">=</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">kubectl</span></span></code></pre></div> <p>Und <code>kubectl get</code> wird zu <code>kg</code>.</p> <div class="mdsvex-shiki shiki shiki-themes catppuccin-mocha" tabindex="0" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4"><div class="header"><span class="language"><svg class="icon" width="16" height="16" viewBox="0 0 576 512" fill="currentColor" aria-hidden="true"><path d="M360.8 1.2c-17-4.9-34.7 5-39.6 22l-128 448c-4.9 17 5 34.7 22 39.6s34.7-5 39.6-22l128-448c4.9-17-5-34.7-22-39.6zm64.6 136.1c-12.5 12.5-12.5 32.8 0 45.3l73.4 73.4-73.4 73.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l96-96c12.5-12.5 12.5-32.8 0-45.3l-96-96c-12.5-12.5-32.8-12.5-45.3 0zm-274.7 0c-12.5-12.5-32.8-12.5-45.3 0l-96 96c-12.5 12.5-12.5 32.8 0 45.3l96 96c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256 150.6 182.6c12.5-12.5 12.5-32.8 0-45.3z"></path></svg>shell</span><button class="copy" data-code="alias kg='kubectl get'" type="button" aria-label="Copy code"><svg class="icon copy-icon" width="16" height="16" viewBox="0 0 448 512" fill="currentColor" aria-hidden="true"><path d="M384 336l-192 0c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l133.5 0c4.2 0 8.3 1.7 11.3 4.7l58.5 58.5c3 3 4.7 7.1 4.7 11.3L400 320c0 8.8-7.2 16-16 16zM192 384l192 0c35.3 0 64-28.7 64-64l0-197.5c0-17-6.7-33.3-18.7-45.3L370.7 18.7C358.7 6.7 342.5 0 325.5 0L192 0c-35.3 0-64 28.7-64 64l0 256c0 35.3 28.7 64 64 64zM64 128c-35.3 0-64 28.7-64 64L0 448c0 35.3 28.7 64 64 64l192 0c35.3 0 64-28.7 64-64l0-16-48 0 0 16c0 8.8-7.2 16-16 16L64 464c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l16 0 0-48-16 0z"></path></svg><svg class="icon check-icon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z"></path></svg></button></div><pre class="shiki shiki-themes catppuccin-mocha catppuccin-mocha" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4" tabindex="0"><code><span class="line"><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">alias</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> kg</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">=</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">'kubectl get'</span></span></code></pre></div> <p>Die nächsten Abkürzungen würde ich dann nur noch im Codeblock kurz beschreiben, wenn sie nicht selbsterklärend sind:</p> <div class="mdsvex-shiki shiki shiki-themes catppuccin-mocha" tabindex="0" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4"><div class="header"><span class="language"><svg class="icon" width="16" height="16" viewBox="0 0 576 512" fill="currentColor" aria-hidden="true"><path d="M360.8 1.2c-17-4.9-34.7 5-39.6 22l-128 448c-4.9 17 5 34.7 22 39.6s34.7-5 39.6-22l128-448c4.9-17-5-34.7-22-39.6zm64.6 136.1c-12.5 12.5-12.5 32.8 0 45.3l73.4 73.4-73.4 73.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l96-96c12.5-12.5 12.5-32.8 0-45.3l-96-96c-12.5-12.5-32.8-12.5-45.3 0zm-274.7 0c-12.5-12.5-32.8-12.5-45.3 0l-96 96c-12.5 12.5-12.5 32.8 0 45.3l96 96c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256 150.6 182.6c12.5-12.5 12.5-32.8 0-45.3z"></path></svg>shell</span><button class="copy" data-code="alias kl='kubectl logs' # Logs bekommen
alias kx='kubectl exec -i -t' # etwas in einem Pod ausführen
alias kgp='kubectl get pod'
alias kgpA='kubectl get pods -A'
alias kgd='kubectl get deployment'
alias kgdA='kubectl get deployments -A'
alias kgs='kubectl get statefulset'
alias kgsA='kubectl get statfulsets -A'
alias kl_f='kubectl logs -f'
alias kl_f_t='kubectl logs -f --tail=200'
alias k_stats='kubectl describe namespace $(kubens -c) &amp;&amp; printf &quot;\n&quot; &amp;&amp; kubectl get po -o custom-columns=&quot;Name:metadata.name,CPU-request:spec.containers[*].resources.requests.cpu,CPU-limit:spec.containers[*].resources.limits.cpu,MEM-request:spec.containers[*].resources.requests.memory,MEM-limit:spec.containers[*].resources.limits.memory&quot;'" type="button" aria-label="Copy code"><svg class="icon copy-icon" width="16" height="16" viewBox="0 0 448 512" fill="currentColor" aria-hidden="true"><path d="M384 336l-192 0c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l133.5 0c4.2 0 8.3 1.7 11.3 4.7l58.5 58.5c3 3 4.7 7.1 4.7 11.3L400 320c0 8.8-7.2 16-16 16zM192 384l192 0c35.3 0 64-28.7 64-64l0-197.5c0-17-6.7-33.3-18.7-45.3L370.7 18.7C358.7 6.7 342.5 0 325.5 0L192 0c-35.3 0-64 28.7-64 64l0 256c0 35.3 28.7 64 64 64zM64 128c-35.3 0-64 28.7-64 64L0 448c0 35.3 28.7 64 64 64l192 0c35.3 0 64-28.7 64-64l0-16-48 0 0 16c0 8.8-7.2 16-16 16L64 464c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l16 0 0-48-16 0z"></path></svg><svg class="icon check-icon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z"></path></svg></button></div><pre class="shiki shiki-themes catppuccin-mocha catppuccin-mocha" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4" tabindex="0"><code><span class="line"><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">alias</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> kl</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">=</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">'kubectl logs'</span><span style="color:#9399B2;--shiki-light-font-style:italic;--shiki-dark:#9399B2;--shiki-dark-font-style:italic"> # Logs bekommen</span></span>
<span class="line"><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">alias</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> kx</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">=</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">'kubectl exec -i -t'</span><span style="color:#9399B2;--shiki-light-font-style:italic;--shiki-dark:#9399B2;--shiki-dark-font-style:italic"> # etwas in einem Pod ausführen</span></span>
<span class="line"><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">alias</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> kgp</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">=</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">'kubectl get pod'</span></span>
<span class="line"><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">alias</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> kgpA</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">=</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">'kubectl get pods -A'</span></span>
<span class="line"><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">alias</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> kgd</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">=</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">'kubectl get deployment'</span></span>
<span class="line"><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">alias</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> kgdA</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">=</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">'kubectl get deployments -A'</span></span>
<span class="line"><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">alias</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> kgs</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">=</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">'kubectl get statefulset'</span></span>
<span class="line"><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">alias</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> kgsA</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">=</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">'kubectl get statfulsets -A'</span></span>
<span class="line"><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">alias</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> kl_f</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">=</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">'kubectl logs -f'</span></span>
<span class="line"><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">alias</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> kl_f_t</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">=</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">'kubectl logs -f --tail=200'</span></span>
<span class="line"><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">alias</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> k_stats</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">=</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">'kubectl describe namespace $(kubens -c) &amp;&amp; printf "\n" &amp;&amp; kubectl get po -o custom-columns="Name:metadata.name,CPU-request:spec.containers[*].resources.requests.cpu,CPU-limit:spec.containers[*].resources.limits.cpu,MEM-request:spec.containers[*].resources.requests.memory,MEM-limit:spec.containers[*].resources.limits.memory"'</span></span></code></pre></div> <p>Für die letzte Abkürzung muss aber <a href="https://github.com/ahmetb/kubectx/tree/master" rel="nofollow">kubens</a> installiert sein und das Ergbnis sieht wie folgt aus:</p> <div class="mdsvex-shiki shiki shiki-themes catppuccin-mocha" tabindex="0" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4"><div class="header"><span class="language"><svg class="icon" width="16" height="16" viewBox="0 0 576 512" fill="currentColor" aria-hidden="true"><path d="M360.8 1.2c-17-4.9-34.7 5-39.6 22l-128 448c-4.9 17 5 34.7 22 39.6s34.7-5 39.6-22l128-448c4.9-17-5-34.7-22-39.6zm64.6 136.1c-12.5 12.5-12.5 32.8 0 45.3l73.4 73.4-73.4 73.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l96-96c12.5-12.5 12.5-32.8 0-45.3l-96-96c-12.5-12.5-32.8-12.5-45.3 0zm-274.7 0c-12.5-12.5-32.8-12.5-45.3 0l-96 96c-12.5 12.5-12.5 32.8 0 45.3l96 96c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256 150.6 182.6c12.5-12.5 12.5-32.8 0-45.3z"></path></svg>shell</span><button class="copy" data-code="# Ausgabe für den Namespace Blog
# Name:         blog
# Labels:       kubernetes.io/metadata.name=blog
# Annotations:  &lt;none>
# Status:       Active

# No resource quota.

# No LimitRange resource.

# Name                        CPU-request   CPU-limit   MEM-request   MEM-limit
# blog-blog-8bbc67694-tz9lp   60m           &lt;none>      50Mi          50Mi" type="button" aria-label="Copy code"><svg class="icon copy-icon" width="16" height="16" viewBox="0 0 448 512" fill="currentColor" aria-hidden="true"><path d="M384 336l-192 0c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l133.5 0c4.2 0 8.3 1.7 11.3 4.7l58.5 58.5c3 3 4.7 7.1 4.7 11.3L400 320c0 8.8-7.2 16-16 16zM192 384l192 0c35.3 0 64-28.7 64-64l0-197.5c0-17-6.7-33.3-18.7-45.3L370.7 18.7C358.7 6.7 342.5 0 325.5 0L192 0c-35.3 0-64 28.7-64 64l0 256c0 35.3 28.7 64 64 64zM64 128c-35.3 0-64 28.7-64 64L0 448c0 35.3 28.7 64 64 64l192 0c35.3 0 64-28.7 64-64l0-16-48 0 0 16c0 8.8-7.2 16-16 16L64 464c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l16 0 0-48-16 0z"></path></svg><svg class="icon check-icon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z"></path></svg></button></div><pre class="shiki shiki-themes catppuccin-mocha catppuccin-mocha" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4" tabindex="0"><code><span class="line"><span style="color:#9399B2;--shiki-light-font-style:italic;--shiki-dark:#9399B2;--shiki-dark-font-style:italic"># Ausgabe für den Namespace Blog</span></span>
<span class="line"><span style="color:#9399B2;--shiki-light-font-style:italic;--shiki-dark:#9399B2;--shiki-dark-font-style:italic"># Name:         blog</span></span>
<span class="line"><span style="color:#9399B2;--shiki-light-font-style:italic;--shiki-dark:#9399B2;--shiki-dark-font-style:italic"># Labels:       kubernetes.io/metadata.name=blog</span></span>
<span class="line"><span style="color:#9399B2;--shiki-light-font-style:italic;--shiki-dark:#9399B2;--shiki-dark-font-style:italic"># Annotations:  &lt;none></span></span>
<span class="line"><span style="color:#9399B2;--shiki-light-font-style:italic;--shiki-dark:#9399B2;--shiki-dark-font-style:italic"># Status:       Active</span></span>
<span class="line"></span>
<span class="line"><span style="color:#9399B2;--shiki-light-font-style:italic;--shiki-dark:#9399B2;--shiki-dark-font-style:italic"># No resource quota.</span></span>
<span class="line"></span>
<span class="line"><span style="color:#9399B2;--shiki-light-font-style:italic;--shiki-dark:#9399B2;--shiki-dark-font-style:italic"># No LimitRange resource.</span></span>
<span class="line"></span>
<span class="line"><span style="color:#9399B2;--shiki-light-font-style:italic;--shiki-dark:#9399B2;--shiki-dark-font-style:italic"># Name                        CPU-request   CPU-limit   MEM-request   MEM-limit</span></span>
<span class="line"><span style="color:#9399B2;--shiki-light-font-style:italic;--shiki-dark:#9399B2;--shiki-dark-font-style:italic"># blog-blog-8bbc67694-tz9lp   60m           &lt;none>      50Mi          50Mi</span></span></code></pre></div> <h2 id="brew">Brew</h2> <p>Ich habe das Glück, auch auf Arbeit einen Mac nutzen zu können und da gehört die Paketverwaltung namens <a href="https://brew.sh" rel="nofollow">Brew</a> einfach dazu. So habe ich auch dafür ein Alias, um die installierten Pakete immer aktuell zu halten:</p> <div class="mdsvex-shiki shiki shiki-themes catppuccin-mocha" tabindex="0" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4"><div class="header"><span class="language"><svg class="icon" width="16" height="16" viewBox="0 0 576 512" fill="currentColor" aria-hidden="true"><path d="M360.8 1.2c-17-4.9-34.7 5-39.6 22l-128 448c-4.9 17 5 34.7 22 39.6s34.7-5 39.6-22l128-448c4.9-17-5-34.7-22-39.6zm64.6 136.1c-12.5 12.5-12.5 32.8 0 45.3l73.4 73.4-73.4 73.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l96-96c12.5-12.5 12.5-32.8 0-45.3l-96-96c-12.5-12.5-32.8-12.5-45.3 0zm-274.7 0c-12.5-12.5-32.8-12.5-45.3 0l-96 96c-12.5 12.5-12.5 32.8 0 45.3l96 96c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256 150.6 182.6c12.5-12.5 12.5-32.8 0-45.3z"></path></svg>shell</span><button class="copy" data-code="alias brewup='brew update &amp;&amp; brew upgrade &amp;&amp; brew outdated &amp;&amp; brew cleanup'" type="button" aria-label="Copy code"><svg class="icon copy-icon" width="16" height="16" viewBox="0 0 448 512" fill="currentColor" aria-hidden="true"><path d="M384 336l-192 0c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l133.5 0c4.2 0 8.3 1.7 11.3 4.7l58.5 58.5c3 3 4.7 7.1 4.7 11.3L400 320c0 8.8-7.2 16-16 16zM192 384l192 0c35.3 0 64-28.7 64-64l0-197.5c0-17-6.7-33.3-18.7-45.3L370.7 18.7C358.7 6.7 342.5 0 325.5 0L192 0c-35.3 0-64 28.7-64 64l0 256c0 35.3 28.7 64 64 64zM64 128c-35.3 0-64 28.7-64 64L0 448c0 35.3 28.7 64 64 64l192 0c35.3 0 64-28.7 64-64l0-16-48 0 0 16c0 8.8-7.2 16-16 16L64 464c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l16 0 0-48-16 0z"></path></svg><svg class="icon check-icon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z"></path></svg></button></div><pre class="shiki shiki-themes catppuccin-mocha catppuccin-mocha" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4" tabindex="0"><code><span class="line"><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">alias</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> brewup</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">=</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">'brew update &amp;&amp; brew upgrade &amp;&amp; brew outdated &amp;&amp; brew cleanup'</span></span></code></pre></div> <p>Ihr seht also, Terminal-Abkürzungen sind echte Zeitsparer. Sie machen den Alltag nicht nur effizienter, sondern helfen auch dabei, Tippfehler bei langen Befehlen zu vermeiden. Wer regelmäßig Aliases nutzt, wird schnell merken, wie viel flüssiger der Workflow läuft. Falls euch meine Sammlung nützlich ist oder ihr coole Ergänzungen habt, lasst es mich gerne wissen – gemeinsam optimieren wir sie weiter!</p>]]></content:encoded>
            <enclosure url="https://timmmi.de/images/meine_terminal_abkuerzungen/aryan-dhiman-iGLLtLINSkw-unsplash-2.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[Ghost sicherer machen]]></title>
            <link>https://timmmi.de/posts/ghost_sicherer_machen</link>
            <guid>https://timmmi.de/posts/ghost_sicherer_machen</guid>
            <pubDate>Sat, 22 Mar 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Ghost fehlt 2FA. Ich zeige, wie du den Admin-Pfad mit OAuth2-Proxy und Tailscale in Kubernetes absicherst – ohne Ghost selbst zu ändern! 🚀]]></description>
            <content:encoded><![CDATA[<p>Zu Ghost als CMS komme ich irgendwie immer wieder zurück. Natürlich habe ich auch schon ein paar andere Alternativen ausprobiert. Unter anderem Wordpress oder Hugo. Aber nach viel Herumprobieren und Reparieren von Pipelines bin ich dann doch wieder bei Ghost. Aber eine Sache stört mich dann doch sehr schnell:</p> <p>Warum zur Hölle kann ich den Admin Account nicht mit einer 2 Faktor Authentifizierung absichern und so geschützter sein?</p> <p>Nun, da Ghost auf meinem Cluster läuft und dort bereits einige Tools in Kubernetes deployed sind, kann ich einfach den entsprechenden Pfad absichern. Genauer gesagt geht es hier um die Pfade, die mit ghost/* beginnen.</p> <h2 id="oauth2-proxy-und-tailscale-to-the-rescue">Oauth2-proxy und Tailscale to the rescue</h2> <p>Zuerst möchte ich kurz erklären, was die beiden Tools OAuth2-proxy und Tailscale machen.</p> <h3 id="oauth2-proxy">OAuth2-proxy</h3> <p>Ich finde die Webseite von <a href="https://oauth2-proxy.github.io/oauth2-proxy/" rel="nofollow">OAuth2-Proxy</a> erklärt es sehr gut in einem Satz:</p> <blockquote><p>A reverse proxy and static file server that provides authentication using Providers (Google, GitHub, and others) to validate accounts by email, domain or group. <a href="https://oauth2-proxy.github.io/oauth2-proxy/" rel="nofollow">Quelle</a></p></blockquote> <p>Das heißt, durch die Möglichkeit eines Reverse Proxy habe ich die Option, bestimmte Pfade abzusichern und gegen einen (Social) Provider zu authentifizieren. In meinem Fall übernimmt das Gitea. Das bedeutet, dass ab diesem Zeitpunkt bei jedem Aufruf von Pfaden, die mit ghost/* beginnen, geprüft wird, ob ich ein gültiges oauth2-proxy-Token als Cookie habe.</p> <p>Aber bekanntlich sagt ein Flow Chart mehr als <em>1000</em> Worte:</p> <figure class="rehype-figure"><img src="../images/ghost_sicherer_machen/Ghost_Oauth2_Proxy.drawio.png" alt="Ghost OAuth2 Proxy" loading="lazy"/><figcaption>Ghost OAuth2 Proxy</figcaption></figure> <h3 id="tailscale">Tailscale</h3> <p>Es gibt einige Programme, die mit der Admin-Api von Ghost umgehen können (z.B. <a href="https://help.ulysses.app/export-publishing/publishing?from_search=175225602#ghost-8" rel="nofollow">Ulysses</a>). In diesen Programmen kann man dann zum Beispiel solche Beiträge schreiben. Sehr nützlich, aber leider überhaupt nicht kompatibel mit einem OAuth2-Flow. Hier kommt Tailscale ins Spiel. Auch hier wieder die Definition von der Homepage, die für sich spricht:</p> <blockquote><p>Tailscale is a mesh VPN (Virtual Private Network) service that streamlines connecting devices and services securely across different networks. It enables encrypted point-to-point connections using the open source <a href="https://www.wireguard.com/" rel="nofollow">WireGuard</a> protocol, which means only devices on your private network can communicate with each other.
Unlike traditional VPNs, which tunnel all network traffic through a central gateway server, Tailscale creates a peer-to-peer mesh network (known as a tailnet). However, you can still use Tailscale like a traditional VPN by routing all traffic through an <a href="https://tailscale.com/kb/1103/exit-node" rel="nofollow">exit node</a>. <a href="https://tailscale.com/kb/1151/what-is-tailscale" rel="nofollow">Quelle</a></p></blockquote> <p>Umgangssprachlich: Man baut einen direkten VPN-Tunnel zu dem Dienst in Kubernetes auf.
Diesen Tunnel kann man aber erst aufbauen, wenn man sich auch im Tailscale VPN eingeloggt hat. Ab diesem Zeitpunkt kann man aber ganz normal auf der Seite surfen. Um das zu ermöglichen, bekommt man von Tailscale eine eigene Domain dafür. D.h. man hat dann eine öffentliche URL (in diesem Fall <a href="https://timmmi.de/" rel="nofollow">timmmi.de</a>) und man hat eine “private/interne” URL.</p> <h2 id="umsetzung">Umsetzung</h2> <p>Genug der Theorie, jetzt komme ich zu dem Teil, wo ich es implementiert habe.</p> <p>Um den geneigten Leser nicht zu sehr zu langweilen, gehe ich an dieser Stelle davon aus, dass der OAuth2-Proxy und Tailscale deployed sind. Das heißt, ich werde nur noch die Details für die richtigen Ingresse in Kubernetes erklären. Nur als Hinweis:</p> <p>Für OAuth2-Proxy habe ich diesen <a href="https://artifacthub.io/packages/helm/oauth2-proxy/oauth2-proxy" rel="nofollow">Helm Chart</a> genutzt</p> <p>und für Tailscale <a href="https://artifacthub.io/packages/helm/tailscale/tailscale-operator" rel="nofollow">dieses</a>:</p> <p>Insgesamt braucht ich 3 <code>Ingress</code>e:</p> <ol><li>ein <code>Ingress</code>, der die <em>Domain</em> und den <em>Pfad</em> <code>ghost/*</code> auf einen OAuth2 Endpunkt weiterleitet</li> <li>ein <code>Ingress</code>, der diesen OAuth2 Endpunkt bereitstellt</li> <li>ein <code>Ingress</code>, der den <code>Service</code> von Ghost im Tailscale Netzwerk bereitstellt</li></ol> <p>⠀
Da ich so etwas vielleicht öfter machen möchte, habe ich es der Einfachheit halber in Jsonnet geschrieben.</p> <p>In diesem Fall habe ich eine Hauptdatei, wo ich definiere, was ich haben will, und ich habe eine Bibliotheksdatei, die die Logik darstellt:</p> <div class="mdsvex-shiki shiki shiki-themes catppuccin-mocha" tabindex="0" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4"><div class="header"><span class="language"><svg class="icon" width="16" height="16" viewBox="0 0 576 512" fill="currentColor" aria-hidden="true"><path d="M360.8 1.2c-17-4.9-34.7 5-39.6 22l-128 448c-4.9 17 5 34.7 22 39.6s34.7-5 39.6-22l128-448c4.9-17-5-34.7-22-39.6zm64.6 136.1c-12.5 12.5-12.5 32.8 0 45.3l73.4 73.4-73.4 73.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l96-96c12.5-12.5 12.5-32.8 0-45.3l-96-96c-12.5-12.5-32.8-12.5-45.3 0zm-274.7 0c-12.5-12.5-32.8-12.5-45.3 0l-96 96c-12.5 12.5-12.5 32.8 0 45.3l96 96c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256 150.6 182.6c12.5-12.5 12.5-32.8 0-45.3z"></path></svg>jsonnet</span><button class="copy" data-code="local o = import 'secure-ingresses.libsonnet';
local ingresses = [
  {
    name: 'ghost-admin',
    namespace: 'ghost',
    domain: 'timmmi.de',
    service: {
      name: 'ghost-ghost',
      port: 2368,
    },
    need: {
      origin: true,
      oauth2: true,
      tailscale: true,
    },
    path: '/ghost/',
    secretName: 'ghost-cert-tls',
  },
];
o.createIngresses(ingresses)" type="button" aria-label="Copy code"><svg class="icon copy-icon" width="16" height="16" viewBox="0 0 448 512" fill="currentColor" aria-hidden="true"><path d="M384 336l-192 0c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l133.5 0c4.2 0 8.3 1.7 11.3 4.7l58.5 58.5c3 3 4.7 7.1 4.7 11.3L400 320c0 8.8-7.2 16-16 16zM192 384l192 0c35.3 0 64-28.7 64-64l0-197.5c0-17-6.7-33.3-18.7-45.3L370.7 18.7C358.7 6.7 342.5 0 325.5 0L192 0c-35.3 0-64 28.7-64 64l0 256c0 35.3 28.7 64 64 64zM64 128c-35.3 0-64 28.7-64 64L0 448c0 35.3 28.7 64 64 64l192 0c35.3 0 64-28.7 64-64l0-16-48 0 0 16c0 8.8-7.2 16-16 16L64 464c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l16 0 0-48-16 0z"></path></svg><svg class="icon check-icon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z"></path></svg></button></div><pre class="shiki shiki-themes catppuccin-mocha catppuccin-mocha" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4" tabindex="0"><code><span class="line"><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">local</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> o </span><span style="color:#94E2D5;--shiki-dark:#94E2D5">=</span><span style="color:#CBA6F7;--shiki-dark:#CBA6F7"> import</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> 'secure-ingresses.libsonnet'</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">;</span></span>
<span class="line"><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">local</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> ingresses </span><span style="color:#94E2D5;--shiki-dark:#94E2D5">=</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> [</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">  {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">    name:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> 'ghost-admin'</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">,</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">    namespace:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> 'ghost'</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">,</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">    domain:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> 'timmmi.de'</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">,</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">    service:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">      name:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> 'ghost-ghost'</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">,</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">      port:</span><span style="color:#FAB387;--shiki-dark:#FAB387"> 2368</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">,</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">    },</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">    need:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">      origin:</span><span style="color:#F38BA8;--shiki-dark:#F38BA8"> true</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">,</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">      oauth2:</span><span style="color:#F38BA8;--shiki-dark:#F38BA8"> true</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">,</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">      tailscale:</span><span style="color:#F38BA8;--shiki-dark:#F38BA8"> true</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">,</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">    },</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">    path:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> '/ghost/'</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">,</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">    secretName:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> 'ghost-cert-tls'</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">,</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">  },</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">];</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">o.</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic">createIngresses</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">(ingresses)</span></span></code></pre></div> <p><em><code>secure-ingresses.jsonnet</code> oder auch die Hauptdatei</em></p> <p>Durch das <code>need</code> kann ich beeinflussen, ob ein “normaler”, ein <code>oauth2</code> oder/und ein <code>tailscale</code> Ingress erstellt wird.</p> <div class="mdsvex-shiki shiki shiki-themes catppuccin-mocha" tabindex="0" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4"><div class="header"><span class="language"><svg class="icon" width="16" height="16" viewBox="0 0 576 512" fill="currentColor" aria-hidden="true"><path d="M360.8 1.2c-17-4.9-34.7 5-39.6 22l-128 448c-4.9 17 5 34.7 22 39.6s34.7-5 39.6-22l128-448c4.9-17-5-34.7-22-39.6zm64.6 136.1c-12.5 12.5-12.5 32.8 0 45.3l73.4 73.4-73.4 73.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l96-96c12.5-12.5 12.5-32.8 0-45.3l-96-96c-12.5-12.5-32.8-12.5-45.3 0zm-274.7 0c-12.5-12.5-32.8-12.5-45.3 0l-96 96c-12.5 12.5-12.5 32.8 0 45.3l96 96c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256 150.6 182.6c12.5-12.5 12.5-32.8 0-45.3z"></path></svg>jsonnet</span><button class="copy" data-code="local nginxIngressClassName = 'nginx';
local tailscaleIngressClassname = 'tailscale';
local oauth2Namespace = 'oauth2-proxy';
local certManagerClusterIssuer = 'clusterIssuer';

local originIngress(ingress) = {
  apiVersion: 'networking.k8s.io/v1',
  kind: 'Ingress',
  metadata: {
    name: std.asciiLower(ingress.name) + '-oauth2',
    annotations: {
      'cert-manager.io/cluster-issuer': certManagerClusterIssuer,
      'nginx.ingress.kubernetes.io/auth-signin': 'https://$host/oauth2/start?rd=$escaped_request_uri',
      'nginx.ingress.kubernetes.io/auth-url': 'https://$host/oauth2/auth',
    },
    namespace: ingress.namespace,
  },
  spec: {
    ingressClassName: nginxIngressClassName,
    rules: [
      {
        host: ingress.domain,
        http: {
          paths: [
            {
              backend: {
                service: {
                  name: ingress.service.name,
                  port: {
                    number: ingress.service.port,
                  },
                },
              },
              path: ingress.path,
              pathType: 'Prefix',
            },
          ],
        },
      },
    ],
    tls: [
      {
        hosts: [
          ingress.domain,
        ],
        secretName: ingress.secretName,
      },
    ],
  },
};

local oauth2Ingress(ingress) = {
  apiVersion: 'networking.k8s.io/v1',
  kind: 'Ingress',
  metadata: {
    name: std.asciiLower(ingress.name) + '-oauth2-endpoint',
    annotations: {
      'cert-manager.io/cluster-issuer': certManagerClusterIssuer,
    },
    namespace: oauth2Namespace,
  },
  spec: {
    ingressClassName: nginxIngressClassName,
    rules: [
      {
        host: ingress.domain,
        http: {
          paths: [
            {
              backend: {
                service: {
                  name: 'oauth2-proxy',
                  port: {
                    number: 80,
                  },
                },
              },
              path: '/oauth2',
              pathType: 'Prefix',
            },
          ],
        },
      },
    ],
    tls: [
      {
        hosts: [
          ingress.domain,
        ],
        secretName: ingress.secretName,
      },
    ],
  },
};

local tailscaleIngress(ingress) = {
  apiVersion: 'networking.k8s.io/v1',
  kind: 'Ingress',
  metadata: {
    name: std.asciiLower(ingress.name) + '-tailscale',
    namespace: ingress.namespace,
  },
  spec: {
    ingressClassName: tailscaleIngressClassname,
    rules: [
      {
        http: {
          paths: [
            {
              backend: {
                service: {
                  name: ingress.service.name,
                  port: {
                    number: ingress.service.port,
                  },
                },
              },
              path: ingress.path,
              pathType: 'Prefix',
            },
          ],
        },
      },
    ],
    tls: [
      {
        hosts: [
          std.asciiLower(ingress.name),
        ],
      },
    ],
  },
};

local createIngresses(ingresses) = std.flattenArrays([
  [
    if ingress.need.origin then originIngress(ingress),
    if ingress.need.oauth2 then oauth2Ingress(ingress),
    if ingress.need.tailscale then tailscaleIngress(ingress),
  ]
  for ingress in ingresses
]);

{
  originIngress: function(ingress) originIngress(ingress),
  oauth2Ingress: function(ingress) oauth2Ingress(ingress),
  tailscaleIngress: function(ingress) tailscaleIngress(ingress),
  createIngresses: function(ingresses) createIngresses(ingresses),
}" type="button" aria-label="Copy code"><svg class="icon copy-icon" width="16" height="16" viewBox="0 0 448 512" fill="currentColor" aria-hidden="true"><path d="M384 336l-192 0c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l133.5 0c4.2 0 8.3 1.7 11.3 4.7l58.5 58.5c3 3 4.7 7.1 4.7 11.3L400 320c0 8.8-7.2 16-16 16zM192 384l192 0c35.3 0 64-28.7 64-64l0-197.5c0-17-6.7-33.3-18.7-45.3L370.7 18.7C358.7 6.7 342.5 0 325.5 0L192 0c-35.3 0-64 28.7-64 64l0 256c0 35.3 28.7 64 64 64zM64 128c-35.3 0-64 28.7-64 64L0 448c0 35.3 28.7 64 64 64l192 0c35.3 0 64-28.7 64-64l0-16-48 0 0 16c0 8.8-7.2 16-16 16L64 464c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l16 0 0-48-16 0z"></path></svg><svg class="icon check-icon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z"></path></svg></button></div><pre class="shiki shiki-themes catppuccin-mocha catppuccin-mocha" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4" tabindex="0"><code><span class="line"><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">local</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> nginxIngressClassName </span><span style="color:#94E2D5;--shiki-dark:#94E2D5">=</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> 'nginx'</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">;</span></span>
<span class="line"><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">local</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> tailscaleIngressClassname </span><span style="color:#94E2D5;--shiki-dark:#94E2D5">=</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> 'tailscale'</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">;</span></span>
<span class="line"><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">local</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> oauth2Namespace </span><span style="color:#94E2D5;--shiki-dark:#94E2D5">=</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> 'oauth2-proxy'</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">;</span></span>
<span class="line"><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">local</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> certManagerClusterIssuer </span><span style="color:#94E2D5;--shiki-dark:#94E2D5">=</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> 'clusterIssuer'</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">local</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> originIngress</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">(ingress) </span><span style="color:#94E2D5;--shiki-dark:#94E2D5">=</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">  apiVersion:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> 'networking.k8s.io/v1'</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">,</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">  kind:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> 'Ingress'</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">,</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">  metadata:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">    name:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> std.</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic">asciiLower</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">(ingress.name) </span><span style="color:#94E2D5;--shiki-dark:#94E2D5">+</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> '-oauth2'</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">,</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">    annotations:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> {</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">      'cert-manager.io/cluster-issuer'</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> certManagerClusterIssuer,</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">      'nginx.ingress.kubernetes.io/auth-signin'</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> 'https://$host/oauth2/start?rd=$escaped_request_uri'</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">,</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">      'nginx.ingress.kubernetes.io/auth-url'</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> 'https://$host/oauth2/auth'</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">,</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">    },</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">    namespace:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> ingress.namespace,</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">  },</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">  spec:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">    ingressClassName:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> nginxIngressClassName,</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">    rules:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> [</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">      {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">        host:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> ingress.domain,</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">        http:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">          paths:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> [</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">            {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">              backend:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">                service:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">                  name:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> ingress.service.name,</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">                  port:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">                    number:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> ingress.service.port,</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">                  },</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">                },</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">              },</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">              path:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> ingress.path,</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">              pathType:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> 'Prefix'</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">,</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">            },</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">          ],</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">        },</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">      },</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">    ],</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">    tls:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> [</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">      {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">        hosts:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> [</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">          ingress.domain,</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">        ],</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">        secretName:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> ingress.secretName,</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">      },</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">    ],</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">  },</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">local</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> oauth2Ingress</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">(ingress) </span><span style="color:#94E2D5;--shiki-dark:#94E2D5">=</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">  apiVersion:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> 'networking.k8s.io/v1'</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">,</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">  kind:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> 'Ingress'</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">,</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">  metadata:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">    name:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> std.</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic">asciiLower</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">(ingress.name) </span><span style="color:#94E2D5;--shiki-dark:#94E2D5">+</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> '-oauth2-endpoint'</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">,</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">    annotations:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> {</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">      'cert-manager.io/cluster-issuer'</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> certManagerClusterIssuer,</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">    },</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">    namespace:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> oauth2Namespace,</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">  },</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">  spec:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">    ingressClassName:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> nginxIngressClassName,</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">    rules:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> [</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">      {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">        host:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> ingress.domain,</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">        http:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">          paths:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> [</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">            {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">              backend:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">                service:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">                  name:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> 'oauth2-proxy'</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">,</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">                  port:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">                    number:</span><span style="color:#FAB387;--shiki-dark:#FAB387"> 80</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">,</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">                  },</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">                },</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">              },</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">              path:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> '/oauth2'</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">,</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">              pathType:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> 'Prefix'</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">,</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">            },</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">          ],</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">        },</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">      },</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">    ],</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">    tls:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> [</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">      {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">        hosts:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> [</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">          ingress.domain,</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">        ],</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">        secretName:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> ingress.secretName,</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">      },</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">    ],</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">  },</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">local</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> tailscaleIngress</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">(ingress) </span><span style="color:#94E2D5;--shiki-dark:#94E2D5">=</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">  apiVersion:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> 'networking.k8s.io/v1'</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">,</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">  kind:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> 'Ingress'</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">,</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">  metadata:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">    name:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> std.</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic">asciiLower</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">(ingress.name) </span><span style="color:#94E2D5;--shiki-dark:#94E2D5">+</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> '-tailscale'</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">,</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">    namespace:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> ingress.namespace,</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">  },</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">  spec:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">    ingressClassName:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> tailscaleIngressClassname,</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">    rules:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> [</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">      {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">        http:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">          paths:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> [</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">            {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">              backend:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">                service:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">                  name:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> ingress.service.name,</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">                  port:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">                    number:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> ingress.service.port,</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">                  },</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">                },</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">              },</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">              path:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> ingress.path,</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">              pathType:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> 'Prefix'</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">,</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">            },</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">          ],</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">        },</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">      },</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">    ],</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">    tls:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> [</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">      {</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">        hosts:</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> [</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">          std.</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic">asciiLower</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">(ingress.name),</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">        ],</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">      },</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">    ],</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">  },</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">local</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> createIngresses</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">(ingresses) </span><span style="color:#94E2D5;--shiki-dark:#94E2D5">=</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> std.flattenArrays</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">([</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">  [</span></span>
<span class="line"><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">    if</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> ingress.need.origin </span><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">then</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> originIngress</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">(ingress),</span></span>
<span class="line"><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">    if</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> ingress.need.oauth2 </span><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">then</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> oauth2Ingress</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">(ingress),</span></span>
<span class="line"><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">    if</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> ingress.need.tailscale </span><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">then</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> tailscaleIngress</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">(ingress),</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">  ]</span></span>
<span class="line"><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">  for</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> ingress </span><span style="color:#CBA6F7;--shiki-dark:#CBA6F7">in</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> ingresses</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">]);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">{</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">  originIngress:</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> function</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">(ingress) </span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic">originIngress</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">(ingress),</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">  oauth2Ingress:</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> function</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">(ingress) </span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic">oauth2Ingress</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">(ingress),</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">  tailscaleIngress:</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> function</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">(ingress) </span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic">tailscaleIngress</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">(ingress),</span></span>
<span class="line"><span style="color:#EBA0AC;--shiki-light-font-style:italic;--shiki-dark:#EBA0AC;--shiki-dark-font-style:italic">  createIngresses:</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> function</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">(ingresses) </span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic">createIngresses</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">(ingresses),</span></span>
<span class="line"><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">}</span></span></code></pre></div> <p><em><code>secure-ingresses.libsonnet</code> oder auch die Bibliotheksdatei</em></p> <p>Da meine HTTP-Zertifikate im Cluster mit dem <a href="https://cert-manager.io" rel="nofollow">CertManager</a> erzeugt werden, sind die richtigen Annotationen direkt enthalten. Der Tailscale Ingress bildet die HTTPs im VPN-Netzwerk ab und liefert eigene Zertifikate aus. D.h. hier wird der CertManager nicht benötigt.</p> <p>Lässt man das Ganze rendern, erhält man folgendes Ergebnis:</p> <p><code>jsonnet secure-ingresses.jsonnet| jq -c '.[]' | while read -r item; do echo "$separator"; echo "$item" | yq -P; separator="—"; done</code></p> <div class="mdsvex-shiki shiki shiki-themes catppuccin-mocha" tabindex="0" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4"><div class="header"><span class="language"><svg class="icon" width="16" height="16" viewBox="0 0 576 512" fill="currentColor" aria-hidden="true"><path d="M360.8 1.2c-17-4.9-34.7 5-39.6 22l-128 448c-4.9 17 5 34.7 22 39.6s34.7-5 39.6-22l128-448c4.9-17-5-34.7-22-39.6zm64.6 136.1c-12.5 12.5-12.5 32.8 0 45.3l73.4 73.4-73.4 73.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l96-96c12.5-12.5 12.5-32.8 0-45.3l-96-96c-12.5-12.5-32.8-12.5-45.3 0zm-274.7 0c-12.5-12.5-32.8-12.5-45.3 0l-96 96c-12.5 12.5-12.5 32.8 0 45.3l96 96c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256 150.6 182.6c12.5-12.5 12.5-32.8 0-45.3z"></path></svg>yaml</span><button class="copy" data-code="---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    cert-manager.io/cluster-issuer: clusterIssuer
    nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri
    nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth
  name: ghost-admin-oauth2
  namespace: ghost
spec:
  ingressClassName: nginx
  rules:
    - host: timmmi.de
      http:
        paths:
          - backend:
              service:
                name: ghost-ghost
                port:
                  number: 2368
            path: /ghost/
            pathType: Prefix
  tls:
    - hosts:
        - timmmi.de
      secretName: ghost-cert-tls
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    cert-manager.io/cluster-issuer: clusterIssuer
  name: ghost-admin-oauth2-endpoint
  namespace: oauth2-proxy
spec:
  ingressClassName: nginx
  rules:
    - host: timmmi.de
      http:
        paths:
          - backend:
              service:
                name: oauth2-proxy
                port:
                  number: 80
            path: /oauth2
            pathType: Prefix
  tls:
    - hosts:
        - timmmi.de
      secretName: ghost-cert-tls
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ghost-admin-tailscale
  namespace: ghost
spec:
  ingressClassName: tailscale
  rules:
    - http:
        paths:
          - backend:
              service:
                name: ghost-ghost
                port:
                  number: 2368
            path: /ghost/
            pathType: Prefix
  tls:
    - hosts:
        - ghost-admin" type="button" aria-label="Copy code"><svg class="icon copy-icon" width="16" height="16" viewBox="0 0 448 512" fill="currentColor" aria-hidden="true"><path d="M384 336l-192 0c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l133.5 0c4.2 0 8.3 1.7 11.3 4.7l58.5 58.5c3 3 4.7 7.1 4.7 11.3L400 320c0 8.8-7.2 16-16 16zM192 384l192 0c35.3 0 64-28.7 64-64l0-197.5c0-17-6.7-33.3-18.7-45.3L370.7 18.7C358.7 6.7 342.5 0 325.5 0L192 0c-35.3 0-64 28.7-64 64l0 256c0 35.3 28.7 64 64 64zM64 128c-35.3 0-64 28.7-64 64L0 448c0 35.3 28.7 64 64 64l192 0c35.3 0 64-28.7 64-64l0-16-48 0 0 16c0 8.8-7.2 16-16 16L64 464c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l16 0 0-48-16 0z"></path></svg><svg class="icon check-icon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z"></path></svg></button></div><pre class="shiki shiki-themes catppuccin-mocha catppuccin-mocha" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4" tabindex="0"><code><span class="line"><span style="color:#F5C2E7;--shiki-dark:#F5C2E7">---</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">apiVersion</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> networking.k8s.io/v1</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">kind</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> Ingress</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">metadata</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">  annotations</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">    cert-manager.io/cluster-issuer</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> clusterIssuer</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">    nginx.ingress.kubernetes.io/auth-signin</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> https://$host/oauth2/start?rd=$escaped_request_uri</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">    nginx.ingress.kubernetes.io/auth-url</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> https://$host/oauth2/auth</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">  name</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> ghost-admin-oauth2</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">  namespace</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> ghost</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">spec</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">  ingressClassName</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> nginx</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">  rules</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#9399B2;--shiki-dark:#9399B2">    -</span><span style="color:#89B4FA;--shiki-dark:#89B4FA"> host</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> timmmi.de</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">      http</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">        paths</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#9399B2;--shiki-dark:#9399B2">          -</span><span style="color:#89B4FA;--shiki-dark:#89B4FA"> backend</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">              service</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">                name</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> ghost-ghost</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">                port</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">                  number</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#FAB387;--shiki-dark:#FAB387"> 2368</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">            path</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> /ghost/</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">            pathType</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> Prefix</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">  tls</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#9399B2;--shiki-dark:#9399B2">    -</span><span style="color:#89B4FA;--shiki-dark:#89B4FA"> hosts</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#9399B2;--shiki-dark:#9399B2">        -</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> timmmi.de</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">      secretName</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> ghost-cert-tls</span></span>
<span class="line"><span style="color:#F5C2E7;--shiki-dark:#F5C2E7">---</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">apiVersion</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> networking.k8s.io/v1</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">kind</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> Ingress</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">metadata</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">  annotations</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">    cert-manager.io/cluster-issuer</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> clusterIssuer</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">  name</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> ghost-admin-oauth2-endpoint</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">  namespace</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> oauth2-proxy</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">spec</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">  ingressClassName</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> nginx</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">  rules</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#9399B2;--shiki-dark:#9399B2">    -</span><span style="color:#89B4FA;--shiki-dark:#89B4FA"> host</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> timmmi.de</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">      http</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">        paths</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#9399B2;--shiki-dark:#9399B2">          -</span><span style="color:#89B4FA;--shiki-dark:#89B4FA"> backend</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">              service</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">                name</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> oauth2-proxy</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">                port</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">                  number</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#FAB387;--shiki-dark:#FAB387"> 80</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">            path</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> /oauth2</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">            pathType</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> Prefix</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">  tls</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#9399B2;--shiki-dark:#9399B2">    -</span><span style="color:#89B4FA;--shiki-dark:#89B4FA"> hosts</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#9399B2;--shiki-dark:#9399B2">        -</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> timmmi.de</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">      secretName</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> ghost-cert-tls</span></span>
<span class="line"><span style="color:#F5C2E7;--shiki-dark:#F5C2E7">---</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">apiVersion</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> networking.k8s.io/v1</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">kind</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> Ingress</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">metadata</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">  name</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> ghost-admin-tailscale</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">  namespace</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> ghost</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">spec</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">  ingressClassName</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> tailscale</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">  rules</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#9399B2;--shiki-dark:#9399B2">    -</span><span style="color:#89B4FA;--shiki-dark:#89B4FA"> http</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">        paths</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#9399B2;--shiki-dark:#9399B2">          -</span><span style="color:#89B4FA;--shiki-dark:#89B4FA"> backend</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">              service</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">                name</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> ghost-ghost</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">                port</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">                  number</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#FAB387;--shiki-dark:#FAB387"> 2368</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">            path</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> /ghost/</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">            pathType</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> Prefix</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">  tls</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#9399B2;--shiki-dark:#9399B2">    -</span><span style="color:#89B4FA;--shiki-dark:#89B4FA"> hosts</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#9399B2;--shiki-dark:#9399B2">        -</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> ghost-admin</span></span></code></pre></div> <p><em>Gerenderte Yaml Datei, die so in den Kubernetes Cluster deployed werden könnte</em></p> <p>Nach dem erfolgreichen Deployment, muss ich mich erst authentifizieren, wenn ich die URL <a href="https://example.com/ghost/#/" rel="nofollow">https://example.com/ghost/#/</a> ansurfe. So bleibt die Administrationsoberfläche geschützt.</p> <h2 id="fazit">Fazit</h2> <p>Mit 2 zusätzlichen Tools, und 3 <code>Ingress</code>en kann man das Admininterface von Ghost ausreichend absichern. Was ich mir allerdings wünschen würde, wäre eine native Lösung von Ghost. Dies wird zumindest auch im Forum immer wieder gefragt und dann nie zufriedenstellend beantwortet:</p> <p><a href="https://www.reddit.com/r/Ghost/comments/12kqe5m/has_anyone_successfully_implemented_2fa_or_mfa/" rel="nofollow">Reddit Kommentar</a></p> <p>Immerhin gibt es mit diesem Post und einigen Commits auf Github ein wenig Hoffnung:</p> <p>Dann hoffe ich weiter…</p> <img src="https://media4.giphy.com/media/v1.Y2lkPTc5MGI3NjExbnF0bjJmeDAycnZxNHlrMXhtd3Fmb29vcGFxdzFrc2NkZ24yYWdwdyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/bIRFRUxcRG3Sw/giphy.gif" alt="Hoffnungsvoll wartender Daumen hoch" loading="lazy"/> <p><em><a href="https://giphy.com/gifs/school-miles-grade-bIRFRUxcRG3Sw" rel="nofollow">Source</a></em></p>]]></content:encoded>
            <enclosure url="https://timmmi.de/images/ghost_sicherer_machen.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[Probleme beim Update des Bitnami Ghost Helm Charts auf die Version 21.0.1]]></title>
            <link>https://timmmi.de/posts/probleme_mit_bitnami_update</link>
            <guid>https://timmmi.de/posts/probleme_mit_bitnami_update</guid>
            <pubDate>Fri, 21 Mar 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Das neueste Update (27.05.2024) des Bitnami Ghost Helm Charts bringt eine unangenehme Überraschung mit sich: einen nicht dokumentierten Migrationspfad. Ohne diesen startet der MySQL Pod nicht mehr, was wiederum den Ghost Blog lahmlegt. Doch keine Panik, ich bin gerade die letzten 2h durch diese Tatsache gegangen und habe…]]></description>
            <content:encoded><![CDATA[<p>Das neueste Update (27.05.2024) des Bitnami Ghost Helm Charts bringt eine unangenehme Überraschung mit sich: einen nicht dokumentierten Migrationspfad. Ohne diesen startet der MySQL Pod nicht mehr, was wiederum den Ghost Blog lahmlegt.</p> <p>Doch keine Panik, ich bin gerade die letzten 2h durch diese Problematik gegangen und habe nun einen guten dokumentierten Weg (auf Englisch), den ihr gerne befolgen könnt:</p> <h2 id="the-workaround">The Workaround</h2> <p><em>At first I found a workaround, add this to your helm chart custom values:</em></p> <div class="mdsvex-shiki shiki shiki-themes catppuccin-mocha" tabindex="0" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4"><div class="header"><span class="language"><svg class="icon" width="16" height="16" viewBox="0 0 576 512" fill="currentColor" aria-hidden="true"><path d="M360.8 1.2c-17-4.9-34.7 5-39.6 22l-128 448c-4.9 17 5 34.7 22 39.6s34.7-5 39.6-22l128-448c4.9-17-5-34.7-22-39.6zm64.6 136.1c-12.5 12.5-12.5 32.8 0 45.3l73.4 73.4-73.4 73.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l96-96c12.5-12.5 12.5-32.8 0-45.3l-96-96c-12.5-12.5-32.8-12.5-45.3 0zm-274.7 0c-12.5-12.5-32.8-12.5-45.3 0l-96 96c-12.5 12.5-12.5 32.8 0 45.3l96 96c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256 150.6 182.6c12.5-12.5 12.5-32.8 0-45.3z"></path></svg>yaml</span><button class="copy" data-code="#...
mysql:
  enabled: true
#...
  auth:
#...
    authenticationPolicy: &quot;mysql_native_password&quot;
  primary:
    configuration: |-
        [mysqld]
        authentication_policy='{{- .Values.auth.authenticationPolicy | default &quot;* ,,&quot; }}'
        mysql_native_password=ON
        skip-name-resolve
        explicit_defaults_for_timestamp
        basedir=/opt/bitnami/mysql
        plugin_dir=/opt/bitnami/mysql/lib/plugin
        port={{ .Values.primary.containerPorts.mysql }}
        mysqlx={{ ternary 1 0 .Values.primary.enableMySQLX }}
        mysqlx_port={{ .Values.primary.containerPorts.mysqlx }}
        socket=/opt/bitnami/mysql/tmp/mysql.sock
        datadir=/bitnami/mysql/data
        tmpdir=/opt/bitnami/mysql/tmp
        max_allowed_packet=16M
        bind-address=*
        pid-file=/opt/bitnami/mysql/tmp/mysqld.pid
        log-error=/opt/bitnami/mysql/logs/mysqld.log
        character-set-server=UTF8
        slow_query_log=0
        long_query_time=10.0

        [client]
        port={{ .Values.primary.containerPorts.mysql }}
        socket=/opt/bitnami/mysql/tmp/mysql.sock
        default-character-set=UTF8
        plugin_dir=/opt/bitnami/mysql/lib/plugin

        [manager]
        port={{ .Values.primary.containerPorts.mysql }}
        socket=/opt/bitnami/mysql/tmp/mysql.sock
        pid-file=/opt/bitnami/mysql/tmp/mysqld.pid
    persistence:
#..." type="button" aria-label="Copy code"><svg class="icon copy-icon" width="16" height="16" viewBox="0 0 448 512" fill="currentColor" aria-hidden="true"><path d="M384 336l-192 0c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l133.5 0c4.2 0 8.3 1.7 11.3 4.7l58.5 58.5c3 3 4.7 7.1 4.7 11.3L400 320c0 8.8-7.2 16-16 16zM192 384l192 0c35.3 0 64-28.7 64-64l0-197.5c0-17-6.7-33.3-18.7-45.3L370.7 18.7C358.7 6.7 342.5 0 325.5 0L192 0c-35.3 0-64 28.7-64 64l0 256c0 35.3 28.7 64 64 64zM64 128c-35.3 0-64 28.7-64 64L0 448c0 35.3 28.7 64 64 64l192 0c35.3 0 64-28.7 64-64l0-16-48 0 0 16c0 8.8-7.2 16-16 16L64 464c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l16 0 0-48-16 0z"></path></svg><svg class="icon check-icon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z"></path></svg></button></div><pre class="shiki shiki-themes catppuccin-mocha catppuccin-mocha" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4" tabindex="0"><code><span class="line"><span style="color:#9399B2;--shiki-light-font-style:italic;--shiki-dark:#9399B2;--shiki-dark-font-style:italic">#...</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">mysql</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">  enabled</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#FAB387;--shiki-dark:#FAB387"> true</span></span>
<span class="line"><span style="color:#9399B2;--shiki-light-font-style:italic;--shiki-dark:#9399B2;--shiki-dark-font-style:italic">#...</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">  auth</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#9399B2;--shiki-light-font-style:italic;--shiki-dark:#9399B2;--shiki-dark-font-style:italic">#...</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">    authenticationPolicy</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> "mysql_native_password"</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">  primary</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">    configuration</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span><span style="color:#CBA6F7;--shiki-dark:#CBA6F7"> |-</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">        [mysqld]</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">        authentication_policy='{{- .Values.auth.authenticationPolicy | default "* ,," }}'</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">        mysql_native_password=ON</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">        skip-name-resolve</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">        explicit_defaults_for_timestamp</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">        basedir=/opt/bitnami/mysql</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">        plugin_dir=/opt/bitnami/mysql/lib/plugin</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">        port={{ .Values.primary.containerPorts.mysql }}</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">        mysqlx={{ ternary 1 0 .Values.primary.enableMySQLX }}</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">        mysqlx_port={{ .Values.primary.containerPorts.mysqlx }}</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">        socket=/opt/bitnami/mysql/tmp/mysql.sock</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">        datadir=/bitnami/mysql/data</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">        tmpdir=/opt/bitnami/mysql/tmp</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">        max_allowed_packet=16M</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">        bind-address=*</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">        pid-file=/opt/bitnami/mysql/tmp/mysqld.pid</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">        log-error=/opt/bitnami/mysql/logs/mysqld.log</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">        character-set-server=UTF8</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">        slow_query_log=0</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">        long_query_time=10.0</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">        [client]</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">        port={{ .Values.primary.containerPorts.mysql }}</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">        socket=/opt/bitnami/mysql/tmp/mysql.sock</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">        default-character-set=UTF8</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">        plugin_dir=/opt/bitnami/mysql/lib/plugin</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">        [manager]</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">        port={{ .Values.primary.containerPorts.mysql }}</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">        socket=/opt/bitnami/mysql/tmp/mysql.sock</span></span>
<span class="line"><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">        pid-file=/opt/bitnami/mysql/tmp/mysqld.pid</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-dark:#89B4FA">    persistence</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">:</span></span>
<span class="line"><span style="color:#9399B2;--shiki-light-font-style:italic;--shiki-dark:#9399B2;--shiki-dark-font-style:italic">#...</span></span></code></pre></div> <h3 id="what-does-that-do">What does that do?</h3> <p>It resets the authentication_policy back to <code>mysql_native_password</code>. To do this, we must then set an additional option in mysql.conf, <code>mysql_native_password=ON</code>. Therefore, the default config was overwritten with all its default options and this value was added.</p> <h3 id="why-did-this-happen">Why did this happen?</h3> <p>The latest Ghost Helm version also uses a new MySQL chart version from Bitnami, where a breaking change regarding authentication has been introduced. Or rather, a long announced deprecation was removed.</p> <p><a href="https://artifacthub.io/packages/helm/bitnami/mysql?ref=timmmi.de#to-11-0-0" rel="nofollow">Source</a></p> <blockquote><p>This major bump uses mysql 8.4 image, that includes several configuration settings, for example the parameter auth.defaultAuthenticationPlugin has been removed in favor of auth.authenticationPolicy. This could potentially break your deployment and you would need to adjust the config settings accordingly.</p></blockquote> <p>Related notes in the deprecation removal in mysql: <a href="https://dev.mysql.com/doc/relnotes/mysql/8.4/en/news-8-4-0.html?ref=timmmi.de#mysqld-8-4-0-deprecation-removal" rel="nofollow">Deprecation Removal MySQL 8.4</a></p> <h3 id="and-what-happens-now-aka-solution">And what happens now aka Solution?</h3> <p>With the above options, the mysql pod will start again and so will Ghost. At this point you should make a backup of your posts at the latest. From this point onwards, you can upgrade to the new authentication method. Follow this guide: <a href="https://dnsmichi.at/2024/05/11/docker-compose-ghost-msql-8-4-msql-native-password-startup-errors-mitigation-solution/?ref=timmmi.de#how-to-migrate-to-cachingsha2password" rel="nofollow">https://dnsmichi.at/2024/05/11/docker-compose-ghost-msql-8-4-msql-native-password-startup-errors-mitigation-solution/#how-to-migrate-to-cachingsha2password</a></p> <p>I am currently trying this out and will then update this comment with the specific commands.</p> <p>Edit: <code>mysql-0</code> is the name of <code>pod</code> running mysql</p> <div class="mdsvex-shiki shiki shiki-themes catppuccin-mocha" tabindex="0" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4"><div class="header"><span class="language"><svg class="icon" width="16" height="16" viewBox="0 0 576 512" fill="currentColor" aria-hidden="true"><path d="M360.8 1.2c-17-4.9-34.7 5-39.6 22l-128 448c-4.9 17 5 34.7 22 39.6s34.7-5 39.6-22l128-448c4.9-17-5-34.7-22-39.6zm64.6 136.1c-12.5 12.5-12.5 32.8 0 45.3l73.4 73.4-73.4 73.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l96-96c12.5-12.5 12.5-32.8 0-45.3l-96-96c-12.5-12.5-32.8-12.5-45.3 0zm-274.7 0c-12.5-12.5-32.8-12.5-45.3 0l-96 96c-12.5 12.5-12.5 32.8 0 45.3l96 96c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256 150.6 182.6c12.5-12.5 12.5-32.8 0-45.3z"></path></svg>shell</span><button class="copy" data-code="kubectl exec -it mysql-0 – bash # connect into the pod with an interactive shell
mysql -u root -p # enter root password afterwards, you will find this information the related secret in your cluster" type="button" aria-label="Copy code"><svg class="icon copy-icon" width="16" height="16" viewBox="0 0 448 512" fill="currentColor" aria-hidden="true"><path d="M384 336l-192 0c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l133.5 0c4.2 0 8.3 1.7 11.3 4.7l58.5 58.5c3 3 4.7 7.1 4.7 11.3L400 320c0 8.8-7.2 16-16 16zM192 384l192 0c35.3 0 64-28.7 64-64l0-197.5c0-17-6.7-33.3-18.7-45.3L370.7 18.7C358.7 6.7 342.5 0 325.5 0L192 0c-35.3 0-64 28.7-64 64l0 256c0 35.3 28.7 64 64 64zM64 128c-35.3 0-64 28.7-64 64L0 448c0 35.3 28.7 64 64 64l192 0c35.3 0 64-28.7 64-64l0-16-48 0 0 16c0 8.8-7.2 16-16 16L64 464c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l16 0 0-48-16 0z"></path></svg><svg class="icon check-icon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z"></path></svg></button></div><pre class="shiki shiki-themes catppuccin-mocha catppuccin-mocha" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4" tabindex="0"><code><span class="line"><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic">kubectl</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> exec</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> -it</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> mysql-0</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> –</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> bash</span><span style="color:#9399B2;--shiki-light-font-style:italic;--shiki-dark:#9399B2;--shiki-dark-font-style:italic"> # connect into the pod with an interactive shell</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic">mysql</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> -u</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> root</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> -p</span><span style="color:#9399B2;--shiki-light-font-style:italic;--shiki-dark:#9399B2;--shiki-dark-font-style:italic"> # enter root password afterwards, you will find this information the related secret in your cluster</span></span></code></pre></div> <div class="mdsvex-shiki shiki shiki-themes catppuccin-mocha" tabindex="0" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4"><div class="header"><span class="language"><svg class="icon" width="16" height="16" viewBox="0 0 576 512" fill="currentColor" aria-hidden="true"><path d="M360.8 1.2c-17-4.9-34.7 5-39.6 22l-128 448c-4.9 17 5 34.7 22 39.6s34.7-5 39.6-22l128-448c4.9-17-5-34.7-22-39.6zm64.6 136.1c-12.5 12.5-12.5 32.8 0 45.3l73.4 73.4-73.4 73.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l96-96c12.5-12.5 12.5-32.8 0-45.3l-96-96c-12.5-12.5-32.8-12.5-45.3 0zm-274.7 0c-12.5-12.5-32.8-12.5-45.3 0l-96 96c-12.5 12.5-12.5 32.8 0 45.3l96 96c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256 150.6 182.6c12.5-12.5 12.5-32.8 0-45.3z"></path></svg>shell</span><button class="copy" data-code="mysql> SELECT User, Host, plugin FROM mysql.user;
+------------------+-----------+-----------------------+
| User             | Host      | plugin                |
+------------------+-----------+-----------------------+
| bn_ghost         | %         | mysql_native_password |
| root             | %         | mysql_native_password |
| mysql.infoschema | localhost | caching_sha2_password |
| mysql.session    | localhost | caching_sha2_password |
| mysql.sys        | localhost | caching_sha2_password |
+------------------+-----------+-----------------------+
5 rows in set (0.00 sec)" type="button" aria-label="Copy code"><svg class="icon copy-icon" width="16" height="16" viewBox="0 0 448 512" fill="currentColor" aria-hidden="true"><path d="M384 336l-192 0c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l133.5 0c4.2 0 8.3 1.7 11.3 4.7l58.5 58.5c3 3 4.7 7.1 4.7 11.3L400 320c0 8.8-7.2 16-16 16zM192 384l192 0c35.3 0 64-28.7 64-64l0-197.5c0-17-6.7-33.3-18.7-45.3L370.7 18.7C358.7 6.7 342.5 0 325.5 0L192 0c-35.3 0-64 28.7-64 64l0 256c0 35.3 28.7 64 64 64zM64 128c-35.3 0-64 28.7-64 64L0 448c0 35.3 28.7 64 64 64l192 0c35.3 0 64-28.7 64-64l0-16-48 0 0 16c0 8.8-7.2 16-16 16L64 464c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l16 0 0-48-16 0z"></path></svg><svg class="icon check-icon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z"></path></svg></button></div><pre class="shiki shiki-themes catppuccin-mocha catppuccin-mocha" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4" tabindex="0"><code><span class="line"><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic">mysql</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">> </span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">SELECT</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> User,</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> Host,</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> plugin</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> FROM</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> mysql.user</span><span style="color:#9399B2;--shiki-dark:#9399B2">;</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic">+------------------+-----------+-----------------------+</span></span>
<span class="line"><span style="color:#94E2D5;--shiki-dark:#94E2D5">|</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> User</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">             |</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> Host</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">      |</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> plugin</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">                |</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic">+------------------+-----------+-----------------------+</span></span>
<span class="line"><span style="color:#94E2D5;--shiki-dark:#94E2D5">|</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> bn_ghost</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">         |</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> %</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">         |</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> mysql_native_password</span><span style="color:#94E2D5;--shiki-dark:#94E2D5"> |</span></span>
<span class="line"><span style="color:#94E2D5;--shiki-dark:#94E2D5">|</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> root</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">             |</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> %</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">         |</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> mysql_native_password</span><span style="color:#94E2D5;--shiki-dark:#94E2D5"> |</span></span>
<span class="line"><span style="color:#94E2D5;--shiki-dark:#94E2D5">|</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> mysql.infoschema</span><span style="color:#94E2D5;--shiki-dark:#94E2D5"> |</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> localhost</span><span style="color:#94E2D5;--shiki-dark:#94E2D5"> |</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> caching_sha2_password</span><span style="color:#94E2D5;--shiki-dark:#94E2D5"> |</span></span>
<span class="line"><span style="color:#94E2D5;--shiki-dark:#94E2D5">|</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> mysql.session</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">    |</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> localhost</span><span style="color:#94E2D5;--shiki-dark:#94E2D5"> |</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> caching_sha2_password</span><span style="color:#94E2D5;--shiki-dark:#94E2D5"> |</span></span>
<span class="line"><span style="color:#94E2D5;--shiki-dark:#94E2D5">|</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> mysql.sys</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">        |</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> localhost</span><span style="color:#94E2D5;--shiki-dark:#94E2D5"> |</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> caching_sha2_password</span><span style="color:#94E2D5;--shiki-dark:#94E2D5"> |</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic">+------------------+-----------+-----------------------+</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic">5</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> rows</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> in</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> set</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> (0.00 </span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">sec</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">)</span></span></code></pre></div> <p>Now we change to the new authentication method: caching_sha2_password. <strong>But you should dump your database before!</strong> Open another terminal for the next command.</p> <div class="mdsvex-shiki shiki shiki-themes catppuccin-mocha" tabindex="0" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4"><div class="header"><span class="language"><svg class="icon" width="16" height="16" viewBox="0 0 576 512" fill="currentColor" aria-hidden="true"><path d="M360.8 1.2c-17-4.9-34.7 5-39.6 22l-128 448c-4.9 17 5 34.7 22 39.6s34.7-5 39.6-22l128-448c4.9-17-5-34.7-22-39.6zm64.6 136.1c-12.5 12.5-12.5 32.8 0 45.3l73.4 73.4-73.4 73.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l96-96c12.5-12.5 12.5-32.8 0-45.3l-96-96c-12.5-12.5-32.8-12.5-45.3 0zm-274.7 0c-12.5-12.5-32.8-12.5-45.3 0l-96 96c-12.5 12.5-12.5 32.8 0 45.3l96 96c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256 150.6 182.6c12.5-12.5 12.5-32.8 0-45.3z"></path></svg>shell</span><button class="copy" data-code="kubectl exec -it mysql-0 – /bin/sh -c  &quot;mysqldump -u root -p&lt;EnterPasswordHereWithoutALeadingSpace> --databases &lt;EnterDatabaseNameHere>&quot; >dump.sql" type="button" aria-label="Copy code"><svg class="icon copy-icon" width="16" height="16" viewBox="0 0 448 512" fill="currentColor" aria-hidden="true"><path d="M384 336l-192 0c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l133.5 0c4.2 0 8.3 1.7 11.3 4.7l58.5 58.5c3 3 4.7 7.1 4.7 11.3L400 320c0 8.8-7.2 16-16 16zM192 384l192 0c35.3 0 64-28.7 64-64l0-197.5c0-17-6.7-33.3-18.7-45.3L370.7 18.7C358.7 6.7 342.5 0 325.5 0L192 0c-35.3 0-64 28.7-64 64l0 256c0 35.3 28.7 64 64 64zM64 128c-35.3 0-64 28.7-64 64L0 448c0 35.3 28.7 64 64 64l192 0c35.3 0 64-28.7 64-64l0-16-48 0 0 16c0 8.8-7.2 16-16 16L64 464c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l16 0 0-48-16 0z"></path></svg><svg class="icon check-icon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z"></path></svg></button></div><pre class="shiki shiki-themes catppuccin-mocha catppuccin-mocha" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4" tabindex="0"><code><span class="line"><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic">kubectl</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> exec</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> -it</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> mysql-0</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> –</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> /bin/sh</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> -c</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">  "mysqldump -u root -p&lt;EnterPasswordHereWithoutALeadingSpace> --databases &lt;EnterDatabaseNameHere>"</span><span style="color:#94E2D5;--shiki-dark:#94E2D5"> ></span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">dump.sql</span></span></code></pre></div> <p>Now go back to the previous terminal. The authentication method will now be changed.</p> <div class="mdsvex-shiki shiki shiki-themes catppuccin-mocha" tabindex="0" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4"><div class="header"><span class="language"><svg class="icon" width="16" height="16" viewBox="0 0 576 512" fill="currentColor" aria-hidden="true"><path d="M360.8 1.2c-17-4.9-34.7 5-39.6 22l-128 448c-4.9 17 5 34.7 22 39.6s34.7-5 39.6-22l128-448c4.9-17-5-34.7-22-39.6zm64.6 136.1c-12.5 12.5-12.5 32.8 0 45.3l73.4 73.4-73.4 73.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l96-96c12.5-12.5 12.5-32.8 0-45.3l-96-96c-12.5-12.5-32.8-12.5-45.3 0zm-274.7 0c-12.5-12.5-32.8-12.5-45.3 0l-96 96c-12.5 12.5-12.5 32.8 0 45.3l96 96c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256 150.6 182.6c12.5-12.5 12.5-32.8 0-45.3z"></path></svg>shell</span><button class="copy" data-code="mysql> ALTER USER 'root'@'%' IDENTIFIED WITH caching_sha2_password BY '&lt;EnterYourPasswordForRootHere>';
Query OK, 0 rows affected, 1 warning (0.05 sec)
mysql>  ALTER USER 'bn_ghost'@'%' IDENTIFIED WITH caching_sha2_password BY 'EnterYourPasswordForbn_ghostHere';
Query OK, 0 rows affected, 1 warning (0.02 sec)
mysql> SELECT User, Host, plugin FROM mysql.user;
+------------------+-----------+-----------------------+
| User             | Host      | plugin                |
+------------------+-----------+-----------------------+
| bn_ghost         | %         | caching_sha2_password |
| root             | %         | caching_sha2_password |
| mysql.infoschema | localhost | caching_sha2_password |
| mysql.session    | localhost | caching_sha2_password |
| mysql.sys        | localhost | caching_sha2_password |
+------------------+-----------+-----------------------+
5 rows in set (0.00 sec)" type="button" aria-label="Copy code"><svg class="icon copy-icon" width="16" height="16" viewBox="0 0 448 512" fill="currentColor" aria-hidden="true"><path d="M384 336l-192 0c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l133.5 0c4.2 0 8.3 1.7 11.3 4.7l58.5 58.5c3 3 4.7 7.1 4.7 11.3L400 320c0 8.8-7.2 16-16 16zM192 384l192 0c35.3 0 64-28.7 64-64l0-197.5c0-17-6.7-33.3-18.7-45.3L370.7 18.7C358.7 6.7 342.5 0 325.5 0L192 0c-35.3 0-64 28.7-64 64l0 256c0 35.3 28.7 64 64 64zM64 128c-35.3 0-64 28.7-64 64L0 448c0 35.3 28.7 64 64 64l192 0c35.3 0 64-28.7 64-64l0-16-48 0 0 16c0 8.8-7.2 16-16 16L64 464c-8.8 0-16-7.2-16-16l0-256c0-8.8 7.2-16 16-16l16 0 0-48-16 0z"></path></svg><svg class="icon check-icon" width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z"></path></svg></button></div><pre class="shiki shiki-themes catppuccin-mocha catppuccin-mocha" style="background-color:#1e1e2e;--shiki-dark-bg:#1e1e2e;color:#cdd6f4;--shiki-dark:#cdd6f4" tabindex="0"><code><span class="line"><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic">mysql</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">> </span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">ALTER</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> USER</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> 'root'@'%'</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> IDENTIFIED</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> WITH</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> caching_sha2_password</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> BY</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> '&lt;EnterYourPasswordForRootHere>'</span><span style="color:#9399B2;--shiki-dark:#9399B2">;</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic">Query</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> OK,</span><span style="color:#FAB387;--shiki-dark:#FAB387"> 0</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> rows</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> affected,</span><span style="color:#FAB387;--shiki-dark:#FAB387"> 1</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> warning</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> (0.05 </span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">sec</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">)</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic">mysql</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">>  </span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">ALTER</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> USER</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> 'bn_ghost'@'%'</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> IDENTIFIED</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> WITH</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> caching_sha2_password</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> BY</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> 'EnterYourPasswordForbn_ghostHere'</span><span style="color:#9399B2;--shiki-dark:#9399B2">;</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic">Query</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> OK,</span><span style="color:#FAB387;--shiki-dark:#FAB387"> 0</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> rows</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> affected,</span><span style="color:#FAB387;--shiki-dark:#FAB387"> 1</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> warning</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> (0.02 </span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">sec</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">)</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic">mysql</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">> </span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">SELECT</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> User,</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> Host,</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> plugin</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> FROM</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> mysql.user</span><span style="color:#9399B2;--shiki-dark:#9399B2">;</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic">+------------------+-----------+-----------------------+</span></span>
<span class="line"><span style="color:#94E2D5;--shiki-dark:#94E2D5">|</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> User</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">             |</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> Host</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">      |</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> plugin</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">                |</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic">+------------------+-----------+-----------------------+</span></span>
<span class="line"><span style="color:#94E2D5;--shiki-dark:#94E2D5">|</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> bn_ghost</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">         |</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> %</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">         |</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> caching_sha2_password</span><span style="color:#94E2D5;--shiki-dark:#94E2D5"> |</span></span>
<span class="line"><span style="color:#94E2D5;--shiki-dark:#94E2D5">|</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> root</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">             |</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> %</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">         |</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> caching_sha2_password</span><span style="color:#94E2D5;--shiki-dark:#94E2D5"> |</span></span>
<span class="line"><span style="color:#94E2D5;--shiki-dark:#94E2D5">|</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> mysql.infoschema</span><span style="color:#94E2D5;--shiki-dark:#94E2D5"> |</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> localhost</span><span style="color:#94E2D5;--shiki-dark:#94E2D5"> |</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> caching_sha2_password</span><span style="color:#94E2D5;--shiki-dark:#94E2D5"> |</span></span>
<span class="line"><span style="color:#94E2D5;--shiki-dark:#94E2D5">|</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> mysql.session</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">    |</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> localhost</span><span style="color:#94E2D5;--shiki-dark:#94E2D5"> |</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> caching_sha2_password</span><span style="color:#94E2D5;--shiki-dark:#94E2D5"> |</span></span>
<span class="line"><span style="color:#94E2D5;--shiki-dark:#94E2D5">|</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> mysql.sys</span><span style="color:#94E2D5;--shiki-dark:#94E2D5">        |</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> localhost</span><span style="color:#94E2D5;--shiki-dark:#94E2D5"> |</span><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic"> caching_sha2_password</span><span style="color:#94E2D5;--shiki-dark:#94E2D5"> |</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic">+------------------+-----------+-----------------------+</span></span>
<span class="line"><span style="color:#89B4FA;--shiki-light-font-style:italic;--shiki-dark:#89B4FA;--shiki-dark-font-style:italic">5</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> rows</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> in</span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1"> set</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4"> (0.00 </span><span style="color:#A6E3A1;--shiki-dark:#A6E3A1">sec</span><span style="color:#CDD6F4;--shiki-dark:#CDD6F4">)</span></span></code></pre></div> <p>Now you can <code>exit</code> mysql and <code>exit</code> the <code>pod</code> and remove the options added above regarding the <code>mysql_native_password</code> and restart your <code>helm</code> deployment and cross your fingers. (remove mysql.auth.authenticationPolicy and mysql.primary.configuration)</p> <p>First the mysql <code>pod</code> should restart and become <code>healthy</code> with the <code>livenessProbe</code>. Then the <code>deployment</code> of ghost should be restarted, as it is probably currently in a crash loop. After the initialization is done and this <code>pod</code> is also <code>healthy</code>, your <code>Ingress</code> should work again and the blog should be accessible without data loss. If something went wrong, you should now have the dump of your MySQL and the exported blog posts. You can now start from a fresh state.</p> <p>Diesen Kommentar habe ich auch in das bereits geöffnete <a href="https://github.com/bitnami/charts/issues/26468?ref=timmmi.de#issuecomment-2138103108" rel="nofollow">Issue</a> gepostet. Ich bin gespannt, ob Bitnami, die Hersteller des Charts, noch etwas in die neueren Versionen des Charts übernehmen, damit dieser Migrationspfad etwas <em>smoother</em> wird.</p>]]></content:encoded>
            <enclosure url="https://timmmi.de/images/probleme_mit_bitnami_update.png" length="0" type="image/png"/>
        </item>
    </channel>
</rss>