<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Projekte &#8211; FOUNDIC.org</title>
	<atom:link href="https://www.foundic.org/de/category/projekte/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.foundic.org</link>
	<description>KI-News &#124; Schulungen &#124; Praxisprojekte</description>
	<lastBuildDate>Sat, 18 Apr 2026 20:33:59 +0000</lastBuildDate>
	<language>de</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://www.foundic.org/wp-content/uploads/2026/02/cropped-Favicon-FOUNDIC-1-32x32.png</url>
	<title>Projekte &#8211; FOUNDIC.org</title>
	<link>https://www.foundic.org</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>WordPress zweisprachig machen – Polylang DE/EN Schritt-für-Schritt Anleitung</title>
		<link>https://www.foundic.org/de/wordpress-zweisprachig-machen-polylang-de-en-anleitung/</link>
					<comments>https://www.foundic.org/de/wordpress-zweisprachig-machen-polylang-de-en-anleitung/#respond</comments>
		
		<dc:creator><![CDATA[Michael Müller]]></dc:creator>
		<pubDate>Sun, 12 Apr 2026 17:48:00 +0000</pubDate>
				<category><![CDATA[Projekte]]></category>
		<guid isPermaLink="false">https://www.foundic.org/?p=1672</guid>

					<description><![CDATA[Deine Website spricht nur Deutsch. Deine Besucher vielleicht nicht. Das ist kein Problem – es ist ein lösbares Problem. Mit&#160;Polylang, einem kostenlosen WordPress-Plugin, bekommt deine Seite eine zweite Sprache. Kein teures Upgrade, keine Agentur, kein Neustart. Nur ein Plugin, ein paar Einstellungen – und am Ende ein kleiner&#160;DE &#124; EN&#160;Schalter im Header, der die aktive [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Deine Website spricht nur Deutsch. Deine Besucher vielleicht nicht.</p>



<p>Das ist kein Problem – es ist ein lösbares Problem. Mit&nbsp;<strong>Polylang</strong>, einem kostenlosen WordPress-Plugin, bekommt deine Seite eine zweite Sprache. Kein teures Upgrade, keine Agentur, kein Neustart. Nur ein Plugin, ein paar Einstellungen – und am Ende ein kleiner&nbsp;<strong>DE | EN</strong>&nbsp;Schalter im Header, der die aktive Sprache fett und in deiner Akzentfarbe hervorhebt.</p>



<p>Dieser Guide dokumentiert die Live-Einrichtung auf foundic.org im März 2026 – mit allem, was dabei schiefgegangen ist, wie es repariert wurde, und was du daraus nicht selbst lernen musst.</p>



<p><strong>Um diese Anleitung verständlicher zu machen, begleiten dich drei Personen:</strong><br>Die typischen Büro-Charaktere: Die kompetente IT-Kollegin, der selbsternannte Experte und der ehrliche Anfänger. Diese drei Perspektiven helfen dir, typische Stolperfallen zu erkennen.<br><strong>Tanja</strong>&nbsp;ist die IT-Expertin. Sie weiß, wie es funktioniert, erklärt geduldig und strukturiert – und lässt sich von schlechten Ratschlägen nicht aus der Ruhe bringen. Wenn du eine Frage hast, hat Tanja die Antwort.<br><strong>Bernd</strong>&nbsp;ist der selbsternannte „Experte“, der alles besser weiß – und meistens falsch liegt. Seine Abkürzungen und sein Halbwissen führen regelmäßig zu Problemen. Er steht für alle gefährlichen Mythen und schlechten Praktiken, die du vermeiden solltest.<br><strong>Ulf</strong>&nbsp;ist der Lernende, genau wie du. Er stellt die Fragen, die dir im Kopf herumschwirren, und braucht manchmal einen Vergleich aus dem Alltag, um IT zu verstehen. Wenn Ulf etwas nicht versteht, ist das völlig in Ordnung, dafür ist Tanja da.&nbsp;</p>



<p><strong>&#8222;Und… Action!&#8220;</strong></p>



<p>Es ist Montagmorgen. Bernd steht am Whiteboard. Auf dem Board steht in großen Buchstaben: „ZWEISPRACHIG – easy peasy.&#8220;</p>



<p><strong>Bernd:</strong>&nbsp;„Ich hab das am Wochenende einfach gemacht. Zwei Sprachen, zehn Minuten, fertig. Was soll da groß schiefgehen?&#8220;<br><strong>Ulf:</strong>&nbsp;„Und? Hat&#8217;s geklappt?&#8220;<br><strong>Bernd:</strong>&nbsp;„Naja&#8230; die Seite war kurz offline. Aber das war der Server.&#8220;<br><strong>Tanja:</strong>&nbsp;„Das war nicht der Server, Bernd. Das war functions.php. Aber fangen wir von vorne an.&#8220;</p>



<h2 class="wp-block-heading">Welchen Weg nimmst du?</h2>



<p><strong>Aufbau dieses Guides:</strong>&nbsp;Teil 1–3 beschreiben die universelle Polylang-Standardeinrichtung – das funktioniert auf jeder WordPress-Installation. Ab Teil 4 folgt eine projektspezifische Lösung für das Astra-Free-Theme. Wähle vorab, welche Variante zu deinem Setup passt:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Variante</th><th>Für wen</th><th>Aufwand</th></tr></thead><tbody><tr><td><strong>A &#8211; Standard</strong>&nbsp;(Teil 1–3)</td><td>Alle WordPress-Setups; Switcher erscheint im Menü rechts</td><td>Gering, wartungsarm</td></tr><tr><td><strong>B &#8211; Astra Free zentriert</strong>&nbsp;(Teil 1–4)</td><td>Astra Free, DE|EN dauerhaft sichtbar und zentriert</td><td>Mittel, manueller HTML-Block</td></tr><tr><td><strong>C &#8211; Entwicklerlösung</strong></td><td>Dynamischer Switcher per Theme-Hook oder Shortcode</td><td>Hoch, kein statischer HTML-Block</td></tr></tbody></table></figure>



<p><strong>Empfehlung:</strong>&nbsp;Für die meisten Leser ist&nbsp;<strong>Variante A</strong>&nbsp;der richtige Einstieg, wartungsarm, dynamisch, funktioniert auf jedem Theme.&nbsp;<strong>Variante B</strong>&nbsp;ist sinnvoll, wenn du Astra Free verwendest und DE|EN dauerhaft sichtbar im Header-Zentrum haben möchtest.&nbsp;<strong>Variante C</strong>&nbsp;empfiehlt sich für produktive Sites mit Entwicklerzugriff und langfristiger Wartung.<br>Dieser Guide dokumentiert Variante B vollständig. Variante A ist nach Teil 3 abgeschlossen. Variante C wird am Ende kurz skizziert.</p>



<h2 class="wp-block-heading">Ausgangssituation</h2>



<p>Stell dir vor, deine Website ist ein gut eingerichtetes Büro – alles auf Deutsch beschriftet, alle Ordner, alle Schilder, alle Dokumente. Jetzt kommen internationale Gäste, und du möchtest, dass sie sich genauso gut zurechtfinden wie die deutschen Besucher.</p>



<p>Genau das macht Polylang: Es gibt deiner Website eine zweite Etage – auf Englisch. Gleiche Struktur, gleiche Navigation, aber alles übersetzt. Und ein kleiner Aufzugsknopf im Header –&nbsp;<strong>DE | EN</strong>&nbsp;– bringt Besucher in die richtige Etage.</p>



<p>In diesem Guide arbeiten wir mit foundic.org als Beispiel. Die Seite läuft auf WordPress 6.9.4 mit dem Astra-Theme und ist bisher komplett auf Deutsch. 53 Beiträge, 4 Seiten – und kein einziges englisches Wort in der Navigation.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440081d690&quot;}" data-wp-interactive="core/image" data-wp-key="69e440081d690" class="wp-block-image aligncenter size-large wp-lightbox-container"><img fetchpriority="high" decoding="async" width="1024" height="756" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/04/Bild-1-Ausgangszustand-FOUNDIC.org_-1024x756.png" alt="Bild 1 - Ausgangszustand FOUNDIC.org" class="wp-image-1676" srcset="https://www.foundic.org/wp-content/uploads/2026/04/Bild-1-Ausgangszustand-FOUNDIC.org_-1024x756.png 1024w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-1-Ausgangszustand-FOUNDIC.org_-300x222.png 300w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-1-Ausgangszustand-FOUNDIC.org_-768x567.png 768w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-1-Ausgangszustand-FOUNDIC.org_-1536x1135.png 1536w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-1-Ausgangszustand-FOUNDIC.org_.png 1600w" sizes="(max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 1 &#8211; Ausgangszustand FOUNDIC.org</figcaption></figure>



<p>Das ändert sich jetzt.</p>



<h2 class="wp-block-heading">Was du am Ende haben wirst</h2>



<ul class="wp-block-list">
<li>Einen funktionierenden <strong>DE | EN</strong> Sprachumschalter im Header</li>



<li>Getrennte Navigationsmenüs für Deutsch und Englisch</li>



<li>Korrekte URL-Struktur: <code>foundic.org/</code> für Deutsch, <code>foundic.org/en/</code> für Englisch</li>



<li>Automatische Browsersprache-Erkennung für neue Besucher</li>



<li>Ein solides Fundament, auf dem du Schritt für Schritt englische Inhalte ergänzen kannst</li>
</ul>



<h2 class="wp-block-heading">Voraussetzungen</h2>



<p>Bevor es losgeht: Hast du das alles?</p>



<ul class="wp-block-list">
<li>WordPress-Installation mit Admin-Zugang</li>



<li>Ein Theme, das Menüpositionen unterstützt (z.B. Astra)</li>



<li>Zugriff auf den WordPress Customizer</li>



<li>Optional, aber dringend empfohlen: Ein Hosting-Backup – dazu mehr im Fehlerbehebungs-Kapitel</li>
</ul>



<p><strong>Ulf:</strong>&nbsp;„Backup? Wofür? Ich mach das einfach rückgängig wenn was schiefgeht.&#8220;<br><strong>Tanja:</strong>&nbsp;„Ulf, WordPress hat keinen Rückgängig-Knopf für kaputte PHP-Dateien.&#8220;<br><strong>Bernd:</strong>&nbsp;„Ich brauch keine Backups. Ich mach keine Fehler.&#8220;<br><strong>Tanja:</strong>&nbsp;„Bernd, du hast letzten Monat die halbe Datenbank überschrieben.&#8220;<br><strong>Bernd:</strong>&nbsp;„Das war ein Experiment.&#8220;</p>



<p>Mach das Backup. Es dauert zwei Minuten und rettet dich möglicherweise vor einer sehr unschönen Stunde.</p>



<h2 class="wp-block-heading">Teil 1: Polylang installieren</h2>



<p><strong>Ulf:</strong>&nbsp;„Polylang – klingt nach nem Fußballverein aus Polen.&#8220;<br><strong>Tanja:</strong>&nbsp;„Es ist das meistgenutzte Mehrsprachigkeits-Plugin für WordPress. 800.000 aktive Installationen, 4,5 Sterne. Kostenlos.&#8220;<br><strong>Bernd:</strong>&nbsp;„Ich hätte einfach die Texte auf der Seite manuell auf Englisch geändert. Viel simpler.&#8220;<br><strong>Tanja:</strong>&nbsp;„Dann hättest du keine deutschen Texte mehr.&#8220;<br><strong>Bernd:</strong>&nbsp;„Stimmt. Schlechte Idee.&#8220;</p>



<p>Polylang ist wie ein Dolmetscher, der dauerhaft im Hintergrund sitzt. Du schreibst deine Inhalte einmal auf Deutsch, einmal auf Englisch – und Polylang sorgt dafür, dass der richtige Besucher die richtige Version sieht. Es verwaltet separate URLs, getrennte Menüs und die SEO-Tags, die Google braucht, um die Versionen auseinanderzuhalten.</p>



<p><strong>So installierst du es:</strong><br>Im WordPress-Backend:&nbsp;<strong>Plugins → Plugin hinzufügen → Suchfeld: „polylang&#8220;</strong><br>Polylang erscheint als erstes Ergebnis. Auf&nbsp;<strong>„Jetzt installieren&#8220;</strong>&nbsp;klicken, danach auf&nbsp;<strong>„Aktivieren&#8220;</strong>.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440081e09f&quot;}" data-wp-interactive="core/image" data-wp-key="69e440081e09f" class="wp-block-image aligncenter size-large wp-lightbox-container"><img decoding="async" width="1024" height="756" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/04/Bild-2-Polylang-Suchergebnis-1024x756.png" alt="Bild 2 -Polylang Suchergebnis" class="wp-image-1678" srcset="https://www.foundic.org/wp-content/uploads/2026/04/Bild-2-Polylang-Suchergebnis-1024x756.png 1024w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-2-Polylang-Suchergebnis-300x222.png 300w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-2-Polylang-Suchergebnis-768x567.png 768w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-2-Polylang-Suchergebnis-1536x1135.png 1536w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-2-Polylang-Suchergebnis.png 1600w" sizes="(max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 2 -Polylang Suchergebnis</figcaption></figure>



<p>Nach dem Klick auf „Aktivieren&#8220; startet Polylang automatisch den Einrichtungsassistenten. Nicht wegklicken – der führt dich durch die ersten wichtigen Einstellungen.</p>



<h2 class="wp-block-heading">Teil 2: Einrichtungsassistent durchlaufen</h2>



<p>Der Assistent führt durch vier Schritte:&nbsp;<strong>Sprachen → Medien → Inhalt → Bereit!</strong><br>Stell dir das vor wie das Ausfüllen eines Einstellungsformulars beim neuen Job – vier Seiten, und dann kannst du loslegen. Die Fragen sind einfacher als bei der Steuer.</p>



<h3 class="wp-block-heading">Schritt 1: Sprachen hinzufügen</h3>



<p>Im Dropdown zuerst&nbsp;<strong>„de_DE – Deutsch&#8220;</strong>&nbsp;auswählen, auf&nbsp;<strong>„+ Neue Sprache hinzufügen&#8220;</strong>&nbsp;klicken. Dann&nbsp;<strong>„en_US – English&#8220;</strong>&nbsp;auswählen, wieder auf&nbsp;<strong>„+ Neue Sprache hinzufügen&#8220;</strong>&nbsp;klicken. Beide Sprachen erscheinen in der Liste. Auf&nbsp;<strong>„Fortfahren&#8220;</strong>&nbsp;klicken.</p>



<p><strong>Ulf:</strong>&nbsp;„Warum de_DE und nicht einfach nur Deutsch?&#8220;<br><strong>Tanja:</strong>&nbsp;„Weil es verschiedene Varianten gibt – Deutsch aus Deutschland, aus Österreich, aus der Schweiz. Das Kürzel sagt dem System genau, welches gemeint ist. So wie beim Fußball: FC Bayern ist nicht dasselbe wie FC Bayern Amateure.&#8220;<br><strong>Ulf:</strong>&nbsp;„Ah. Okay. Das ergibt Sinn.&#8220;</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440081e7f9&quot;}" data-wp-interactive="core/image" data-wp-key="69e440081e7f9" class="wp-block-image aligncenter size-large wp-lightbox-container"><img decoding="async" width="1024" height="765" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/04/Bild-3-Beide-Sprachen-DE-und-EN-1024x765.png" alt="Bild 3 - Beide Sprachen DE und EN" class="wp-image-1681" srcset="https://www.foundic.org/wp-content/uploads/2026/04/Bild-3-Beide-Sprachen-DE-und-EN-1024x765.png 1024w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-3-Beide-Sprachen-DE-und-EN-300x224.png 300w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-3-Beide-Sprachen-DE-und-EN-768x574.png 768w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-3-Beide-Sprachen-DE-und-EN-1536x1147.png 1536w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-3-Beide-Sprachen-DE-und-EN.png 1600w" sizes="(max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 3 &#8211; Beide Sprachen DE und EN</figcaption></figure>



<h3 class="wp-block-heading">Schritt 2: Medien-Einstellungen</h3>



<p>Polylang fragt, ob Bilder und Dateien ebenfalls übersetzt werden sollen. Klingt nett, ist aber für die meisten Websites unnötig.</p>



<p>Toggle&nbsp;<strong>deaktiviert</strong>&nbsp;lassen. Auf&nbsp;<strong>„Fortfahren&#8220;</strong>&nbsp;klicken.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440081ee02&quot;}" data-wp-interactive="core/image" data-wp-key="69e440081ee02" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="765" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/04/Bild-4-Wizard-Schritt-Medien-1024x765.png" alt="Bild 4 -Wizard Schritt Medien" class="wp-image-1683" srcset="https://www.foundic.org/wp-content/uploads/2026/04/Bild-4-Wizard-Schritt-Medien-1024x765.png 1024w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-4-Wizard-Schritt-Medien-300x224.png 300w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-4-Wizard-Schritt-Medien-768x574.png 768w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-4-Wizard-Schritt-Medien-1536x1147.png 1536w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-4-Wizard-Schritt-Medien.png 1600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 4 -Wizard Schritt Medien</figcaption></figure>



<p><strong>Was bedeutet das konkret?</strong>&nbsp;Deine Bilder bleiben wie sie sind – ein Bild in der Mediathek, das in beiden Sprachversionen verwendet wird. Du müsstest nur dann aktivieren, wenn du für EN andere Bilder mit englischem Text einblenden möchtest.</p>



<h3 class="wp-block-heading">Schritt 3: Bestehende Inhalte als Deutsch markieren</h3>



<p>Polylang entdeckt jetzt, dass du bereits 53 Beiträge und 4 Seiten hast – und keiner davon ist bisher einer Sprache zugeordnet. Das ist wie ein Büro voller unbeschrifteter Ordner: Es gibt sie, aber niemand weiß, in welche Abteilung sie gehören.</p>



<p><strong>„Deutsch – de_DE&#8220;</strong>&nbsp;auswählen (bereits vorausgewählt) und auf&nbsp;<strong>„Fortfahren&#8220;</strong>&nbsp;klicken. Polylang weist allen bestehenden Beiträgen und Seiten automatisch Deutsch zu – die Grundlage dafür, dass du später englische Übersetzungen anlegen und mit den deutschen Originalen verknüpfen kannst.</p>



<p><strong>Bernd:</strong>&nbsp;„Kann ich da auch einfach alle auf Englisch setzen? Dann muss ich nichts übersetzen.&#8220;<br><strong>Tanja:</strong>&nbsp;„Dann würden deine deutschen Artikel als englische Inhalte geführt. Google würde das bemerken und du bekommst SEO-Probleme.&#8220;<br><strong>Bernd:</strong>&nbsp;„Ach so.&#8220;<br><strong>Tanja:</strong>&nbsp;„Immer Deutsch. Du kannst danach englische Versionen anlegen.&#8220;</p>



<h3 class="wp-block-heading">Schritt 4: Assistent abschließen</h3>



<p>Der Assistent ist fertig. Polylang zeigt eine Bestätigungsseite und schlägt die nächsten Schritte vor.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440081f4c6&quot;}" data-wp-interactive="core/image" data-wp-key="69e440081f4c6" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="801" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/04/Bild-5-Wizard-Bereit-1024x801.png" alt="Bild 5 - Wizard Bereit" class="wp-image-1686" srcset="https://www.foundic.org/wp-content/uploads/2026/04/Bild-5-Wizard-Bereit-1024x801.png 1024w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-5-Wizard-Bereit-300x235.png 300w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-5-Wizard-Bereit-768x601.png 768w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-5-Wizard-Bereit-1536x1202.png 1536w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-5-Wizard-Bereit.png 1600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 5 &#8211; Wizard Bereit</figcaption></figure>



<p>Polylang ist jetzt aktiv. Was noch fehlt: Der Sprachumschalter, den Besucher tatsächlich sehen und klicken können. Den bauen wir in Teil 3.</p>



<h2 class="wp-block-heading">Teil 3: Sprachumschalter im Menü einrichten</h2>



<p>Jetzt wird es sichtbar. Bis hier hat Polylang still im Hintergrund gearbeitet. Jetzt bekommt deine Website ihren ersten öffentlichen Hinweis: „Hey, hier gibt&#8217;s zwei Sprachen.&#8220;<br>Der Sprachumschalter ist wie das Schildchen neben dem Aufzugsknopf. Klein, unscheinbar – aber ohne ihn findet niemand in die zweite Etage.</p>



<h3 class="wp-block-heading">Schritt 5: Menü-Editor öffnen</h3>



<p>Im Backend:&nbsp;<strong>Design → Menüs</strong><br>Der Menü-Editor öffnet sich. Links sieht man jetzt einen neuen Block&nbsp;<strong>„Sprachumschalter&#8220;</strong>&nbsp;– den hat Polylang automatisch hinzugefügt.</p>



<h3 class="wp-block-heading">Schritt 6: Sprachumschalter zum Menü hinzufügen</h3>



<p>Links unter&nbsp;<strong>„Sprachumschalter&#8220;</strong>&nbsp;das Häkchen bei&nbsp;<strong>„Sprachen&#8220;</strong>&nbsp;setzen und auf&nbsp;<strong>„Zum Menü hinzufügen&#8220;</strong>&nbsp;klicken.<br>Im Menü erscheint ein neuer Eintrag&nbsp;<strong>„Sprachen&#8220;</strong>&nbsp;als letzter Punkt.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440081fc69&quot;}" data-wp-interactive="core/image" data-wp-key="69e440081fc69" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="723" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/04/Bild-6-Sprachumschalter-im-Menue-1024x723.png" alt="Bild 6 - Sprachumschalter im Menü" class="wp-image-1688" srcset="https://www.foundic.org/wp-content/uploads/2026/04/Bild-6-Sprachumschalter-im-Menue-1024x723.png 1024w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-6-Sprachumschalter-im-Menue-300x212.png 300w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-6-Sprachumschalter-im-Menue-768x542.png 768w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-6-Sprachumschalter-im-Menue-1536x1085.png 1536w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-6-Sprachumschalter-im-Menue.png 1600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 6 &#8211; Sprachumschalter im Menü</figcaption></figure>



<h3 class="wp-block-heading">Schritt 7: Sprachumschalter konfigurieren</h3>



<p>Den Eintrag&nbsp;<strong>„Sprachen&#8220;</strong>&nbsp;aufklappen (Pfeil rechts klicken). Polylang zeigt dir mehrere Einstellungsoptionen. Lass sie alle&nbsp;<strong>deaktiviert</strong>:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Option</th><th>Einstellung</th><th>Begründung</th></tr></thead><tbody><tr><td>Als Auswahlbox darstellen</td><td>☐ aus</td><td>Links statt Dropdown</td></tr><tr><td>Darstellung der Sprach-Namen</td><td>☐ aus</td><td>Kein „Deutsch&#8220;/„English&#8220; – Kürzel reicht</td></tr><tr><td>Flaggen anzeigen</td><td>☐ aus</td><td>Keine Flaggen, nur Text</td></tr><tr><td>Erzwingt einen Link zur Startseite</td><td>☐ aus</td><td>Switcher soll auf den gleichen Artikel zeigen</td></tr><tr><td>Versteckt die aktuelle Sprache</td><td>☐ aus</td><td>Beide Sprachen immer sichtbar</td></tr><tr><td>Sprachen ohne Übersetzung ausblenden</td><td>☐ aus</td><td>Verhindert zusätzliches Ausblenden verfügbarer Sprachoptionen</td></tr></tbody></table></figure>



<p><strong>Ulf:</strong>&nbsp;„Warum keine Flaggen? Flaggen sind doch cool. Beim Stadion gibt&#8217;s auch Flaggen.&#8220;<br><strong>Tanja:</strong>&nbsp;„Weil Flaggen für Länder stehen, nicht für Sprachen. Englisch ist nicht nur UK. Österreicher sprechen Deutsch und mögen vielleicht kein deutsches Flaggchen.&#8220;<br><strong>Bernd:</strong>&nbsp;„Ich hätte einfach Flaggen genommen und geschaut, ob sich jemand beschwert.&#8220;<br><strong>Tanja:</strong>&nbsp;„Das ist kein Ansatz, Bernd.&#8220;</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e44008202f6&quot;}" data-wp-interactive="core/image" data-wp-key="69e44008202f6" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="723" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/04/Bild-7-Switcher-Einstellungen-korrekt-1024x723.png" alt="Bild 7 - Switcher Einstellungen korrekt" class="wp-image-1690" srcset="https://www.foundic.org/wp-content/uploads/2026/04/Bild-7-Switcher-Einstellungen-korrekt-1024x723.png 1024w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-7-Switcher-Einstellungen-korrekt-300x212.png 300w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-7-Switcher-Einstellungen-korrekt-768x542.png 768w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-7-Switcher-Einstellungen-korrekt-1536x1085.png 1536w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-7-Switcher-Einstellungen-korrekt.png 1600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 7 &#8211; Switcher Einstellungen korrekt</figcaption></figure>



<p>Auf&nbsp;<strong>„Menü speichern&#8220;</strong>&nbsp;klicken.</p>



<p><strong>Wichtig:</strong>&nbsp;WordPress bestätigt mit „Hauptmenü wurde aktualisiert.&#8220; im grünen Banner oben auf der Seite.</p>



<h3 class="wp-block-heading">Schritt 8: CSS für den Sprachumschalter einrichten</h3>



<p>Jetzt kommt die Kosmetik. Polylang zeigt den Sprachumschalter standardmäßig mit dem vollen Sprachnamen – „Deutsch&#8220; und „English&#8220;. Das ist zu lang und zu unelegant. Wir wollen:&nbsp;<strong>DE | EN</strong>. Kompakt, klar, modern.</p>



<p>Das geht über CSS – die Gestaltungssprache des Webs. Keine Angst: Du musst hier nichts erfinden. Kopiere einfach den fertigen Code.</p>



<p>Im Backend:&nbsp;<strong>Design → Customizer → Zusätzliches CSS</strong></p>



<p>Der Customizer öffnet sich mit dem CSS-Editor links und einer Live-Vorschau rechts. Folgenden Code ans Ende des bestehenden CSS anfügen:</p>



<pre class="wp-block-code"><code>/* ===== Sprachumschalter DE | EN ===== */

/* Originaltext ausblenden */
.lang-item a {
    font-size: 0 !important;
    color: #666;
    text-decoration: none;
    padding: 0 3px;
}

/* Sprachkürzel per Pseudo-Element einblenden */
.lang-item.lang-item-de a::after { content: "DE"; font-size: 13px; }
.lang-item.lang-item-en a::after { content: "EN"; font-size: 13px; }

/* Trennstrich | zwischen den Sprachen */
.lang-item + .lang-item::before {
    content: "|";
    color: #ccc;
    font-size: 13px;
    margin-right: 2px;
}

/* Aktive Sprache: fett + Akzentfarbe */
.lang-item.current-lang a::after {
    font-weight: bold;
    color: #e8691e;
}
</code></pre>



<p><strong>Was macht das genau?</strong>&nbsp;Der Code blendet zunächst den Originaltext komplett aus (<code>font-size: 0</code>) und blendet dann per&nbsp;<code>::after</code>&nbsp;die Kürzel „DE&#8220; und „EN&#8220; wieder ein. Der aktiven Sprache gibt er fette Schrift und die Akzentfarbe. Der senkrechte Strich | erscheint automatisch zwischen den beiden Einträgen – kein extra HTML nötig.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400820a58&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400820a58" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="723" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/04/Bild-8-Customizer-CSS-eingefuegt-1024x723.png" alt="Bild 8 - Customizer CSS eingefügt" class="wp-image-1692" srcset="https://www.foundic.org/wp-content/uploads/2026/04/Bild-8-Customizer-CSS-eingefuegt-1024x723.png 1024w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-8-Customizer-CSS-eingefuegt-300x212.png 300w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-8-Customizer-CSS-eingefuegt-768x542.png 768w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-8-Customizer-CSS-eingefuegt-1536x1085.png 1536w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-8-Customizer-CSS-eingefuegt.png 1600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 8 &#8211; Customizer CSS eingefügt</figcaption></figure>



<p>Auf&nbsp;<strong>„Veröffentlichen&#8220;</strong>&nbsp;klicken.</p>



<p><strong>Farbe anpassen:</strong>&nbsp;<code>#e8691e</code>&nbsp;ist die Akzentfarbe von foundic.org. Ersetze diesen Wert durch den Hex-Code deiner Website-Farbe. Den findest du meistens in den Theme-Einstellungen unter „Primärfarbe&#8220;.</p>



<h3 class="wp-block-heading">Schritt 9: Ergebnis im Frontend prüfen</h3>



<p>Website aufrufen:&nbsp;<code>https://deine-domain.de</code></p>



<p>Im Header ist jetzt der Sprachumschalter sichtbar –&nbsp;<strong>DE</strong>&nbsp;erscheint rechts im Menü, in Orange und fett. EN ist noch grau und inaktiv, weil noch keine englischen Inhalte vorhanden sind.</p>



<p>Das ist der erste funktionierende Zwischenstand. Variante-A-Nutzer sind hier fertig – herzlichen Glückwunsch. In Teil 4 gehen wir für Variante B weiter: Der Umschalter wandert in die Mitte des Headers, und EN ist dauerhaft sichtbar.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400821100&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400821100" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="730" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/04/Bild-10-Frontend-Ergebnis-erster-Zwischenstand-1024x730.png" alt="Bild 9 - Frontend Ergebnis erster Zwischenstand" class="wp-image-1695" srcset="https://www.foundic.org/wp-content/uploads/2026/04/Bild-10-Frontend-Ergebnis-erster-Zwischenstand-1024x730.png 1024w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-10-Frontend-Ergebnis-erster-Zwischenstand-300x214.png 300w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-10-Frontend-Ergebnis-erster-Zwischenstand-768x548.png 768w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-10-Frontend-Ergebnis-erster-Zwischenstand-1536x1095.png 1536w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-10-Frontend-Ergebnis-erster-Zwischenstand.png 1585w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 9 &#8211; Frontend Ergebnis erster Zwischenstand</figcaption></figure>



<p><strong>Bis hierhin: Standard-Polylang-Einrichtung abgeschlossen.</strong><br>Was du jetzt hast: einen funktionierenden Sprachumschalter im Menü (rechts in der Navigation), der EN automatisch einblendet, sobald eine englische Übersetzung für die aktuelle Seite vorhanden ist. Das ist der offizielle Polylang-Weg – und für viele Websites ausreichend.</p>



<p><strong>Wann reicht das?</strong></p>



<ul class="wp-block-list">
<li>Du willst nur einen funktionierenden Sprachumschalter: → <strong>fertig, Teil 4 überspringen</strong></li>



<li>Du willst EN immer sichtbar, auch ohne Übersetzungen: → <strong>Teil 4 nötig</strong></li>



<li>Du willst den Umschalter exakt in der Header-Mitte bei Astra Free: → <strong>Teil 4 nötig</strong><br><strong>Die folgenden Schritte sind projektspezifisch</strong> für das Ziel: DE | EN dauerhaft sichtbar und zentriert im Astra-Free-Header.</li>
</ul>



<h2 class="wp-block-heading">Teil 4: Sprachumschalter dauerhaft sichtbar und zentriert (Astra Free)</h2>



<p>Variante B löst ein konkretes Layout-Problem elegant: DE | EN ist dauerhaft im Header sichtbar – unabhängig davon, ob für die aktuelle Seite schon eine Übersetzung existiert. Das gibt der Website von Anfang an ein zweisprachiges Erscheinungsbild, auch wenn die Inhalte noch im Aufbau sind.</p>



<p><strong>Für wen passt Variante B am besten?</strong>&nbsp;Für Corporate- oder Marken-Websites, bei denen das visuelle Erscheinungsbild Priorität hat und der Sprachumschalter von Tag 1 sichtbar sein soll. Für redaktionelle Websites mit vielen Artikeln, bei denen Leser per Klick direkt zur übersetzten Version des aktuellen Artikels gelangen sollen, ist Variante A oder C die robustere Wahl.</p>



<p>Bernd betritt den Raum mit einem frischen Kaffee und dem Gesicht eines Mannes, der gerade eine Idee gehabt hat.</p>



<p><strong>Bernd:</strong>&nbsp;„Ich würde jetzt einfach das Menü umbauen. Drag and Drop. Fünf Minuten.&#8220;<br><strong>Tanja:</strong>&nbsp;„Astra Free hat kein freies Drag-and-Drop im Header Builder. Die Mittelspalte existiert zwar, ist aber standardmäßig null Pixel breit.&#8220;<br><strong>Ulf:</strong>&nbsp;„Null Pixel? Das ist wie eine Auswechselbank ohne Spieler.&#8220;<br><strong>Tanja:</strong>&nbsp;„Genau. Wir bauen die Bank trotzdem auf – per CSS.&#8220;</p>



<h3 class="wp-block-heading">Problem 1: EN-Link fehlt im Sprachumschalter</h3>



<p>Im Menü erscheint zunächst nur&nbsp;<strong>„Deutsch&#8220;</strong>&nbsp;– der EN-Link fehlt komplett.</p>



<p><strong>Das ist kein Fehler</strong>, sondern korrektes Polylang-Verhalten. Polylang zeigt eine Sprache im Switcher nur an, wenn für die aktuell angezeigte Seite eine Übersetzung in dieser Sprache existiert. Da bisher noch keine englischen Inhalte angelegt wurden, bleibt EN unsichtbar.</p>



<p><strong>Die Lösung:</strong>&nbsp;Den Polylang-Menü-Switcher durch ein eigenes HTML-Widget im Astra Header Builder ersetzen, das DE und EN immer zeigt – unabhängig davon, ob Übersetzungen vorhanden sind.</p>



<p><strong>Abwägung: Polylang-Switcher vs. eigenes HTML-Widget</strong></p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Variante</th><th>Vorteil</th><th>Nachteil</th></tr></thead><tbody><tr><td>Polylang-Menü-Switcher</td><td>Dynamisch, wartungsarm, funktioniert automatisch</td><td>Blendet EN aus, wenn keine Übersetzung vorhanden</td></tr><tr><td>Eigenes HTML im Header</td><td>DE|EN immer sichtbar, volle Kontrolle</td><td>Links sind fest eingetragen – bei Domainwechsel, Staging oder Subdirectory-Installation müssen sie manuell angepasst werden</td></tr></tbody></table></figure>



<p>Wir entscheiden uns hier für das HTML-Widget, weil DE|EN dauerhaft sichtbar sein soll.&nbsp;<strong>Denk daran:</strong>&nbsp;Bei einem Domainwechsel oder beim Einrichten einer Staging-Umgebung musst du die Links im Widget manuell aktualisieren.</p>



<h3 class="wp-block-heading">Problem 2: Sprachumschalter soll in der Header-Mitte stehen</h3>



<p>Der Polylang-Menüeintrag erscheint ganz rechts in der Navigation. Gewünscht ist eine Platzierung in der&nbsp;<strong>Mitte des Headers</strong>&nbsp;– zwischen Logo links und Menü rechts.</p>



<p>Stell dir den Header vor wie ein Fußballfeld: Links steht der Torwart (Logo), rechts stürmt die Mannschaft (Menü). Der Sprachumschalter soll der Libero in der Mitte sein – immer präsent, elegant positioniert.</p>



<p>Da Astra Free keine freie Positionierung im Header Builder erlaubt, greifen wir zu einem CSS-Trick:&nbsp;<code>position: absolute</code>. Das klingt gefährlicher als es ist.</p>



<h3 class="wp-block-heading">Schritt 10: Astra Header Builder öffnen</h3>



<p>Im Backend:&nbsp;<strong>Design → Customizer → Header → Header Builder</strong></p>



<p>Der Header Builder zeigt den visuellen Aufbau mit drei Zonen: Links (Logo), Mitte (leer), Rechts (Primäres Menü).</p>



<p><strong>Hinweis bei Astra Free:</strong>&nbsp;Das HTML-2-Widget kann nur in die linke Zone gezogen werden – die Mittelzone ist in der kostenlosen Version gesperrt. Die visuelle Zentrierung erreichen wir über CSS.</p>



<h3 class="wp-block-heading">Schritt 11: HTML 2 Widget einfügen</h3>



<p>Im Header Builder das&nbsp;<strong>„HTML 2&#8243;</strong>-Element aus dem Bereich „Verfügbare Widgets&#8220; in den Header ziehen (linke Zone). Durch Klick auf das Widget öffnet sich ein WYSIWYG-Editor – ein einfaches Textfeld mit Formatierungsknöpfen.</p>



<h3 class="wp-block-heading">Schritt 12: Sprachumschalter-HTML einfügen</h3>



<p>Im Editor folgenden Code eingeben:</p>



<pre class="wp-block-code"><code>&lt;nav class="pll-switcher-center"&gt;
  &lt;a href="https://www.deine-domain.de/" class="pll-link-de" hreflang="de"&gt;DE&lt;/a&gt;
  &lt;span class="pll-sep"&gt;|&lt;/span&gt;
  &lt;a href="https://www.deine-domain.de/en/" class="pll-link-en" hreflang="en"&gt;EN&lt;/a&gt;
&lt;/nav&gt;
</code></pre>



<p><strong>URLs anpassen:</strong>&nbsp;Ersetze&nbsp;<code>deine-domain.de</code>&nbsp;durch deine echte Domain.</p>



<p><strong>Technische Besonderheit:</strong>&nbsp;Der WYSIWYG-Editor fügt nach jedem Element automatisch&nbsp;<code>&lt;br&gt;</code>-Tags ein. Das sieht zunächst seltsam aus – ist aber kein Problem. Das CSS im nächsten Schritt unterdrückt diese Zeilenumbrüche wieder.</p>



<p><strong>Wichtig – Verhalten auf Unterseiten:</strong>&nbsp;Dieser HTML-Switcher ist ein&nbsp;<strong>statisches Widget</strong>. Die Links zeigen immer auf die Startseiten (<code>/</code>&nbsp;bzw.&nbsp;<code>/en/</code>) – unabhängig davon, auf welchem Artikel der Besucher gerade ist. Das bedeutet: Wer auf einem deutschen Artikel auf EN klickt, landet zunächst auf der englischen Startseite, nicht auf der englischen Übersetzung des Artikels.</p>



<p><strong>Für die Startseite und einfache Navigationszwecke ist das ausreichend.</strong>&nbsp;Wer artikelgenaues Umschalten benötigt (Klick auf EN → direkt zur englischen Version des gleichen Artikels), sollte stattdessen den nativen&nbsp;<strong>Polylang-Menü-Switcher</strong>&nbsp;verwenden (Variante A) oder eine dynamische Lösung per Theme-Hook einsetzen (Variante C). Der native Polylang-Switcher ist wartungsärmer und löst diesen Fall automatisch.</p>



<p>Auf&nbsp;<strong>„Veröffentlichen&#8220;</strong>&nbsp;klicken.</p>



<h3 class="wp-block-heading">Schritt 13: CSS vollständig überarbeiten</h3>



<p>Jetzt kommt der entscheidende Schritt: Das CSS aus Schritt 13 muss vollständig ersetzt werden. Das bisherige CSS hat den Polylang-Switcher im Menü gestylt – der ist jetzt nicht mehr zuständig. Das neue CSS stylt das HTML-Widget und positioniert es in der Mitte des Headers.</p>



<p>Im Backend:&nbsp;<strong>Design → Customizer → Zusätzliches CSS</strong></p>



<p>Das bisherige CSS für&nbsp;<code>.lang-item</code>&nbsp;vollständig durch folgenden Code&nbsp;<strong>ersetzen</strong>:</p>



<pre class="wp-block-code"><code>/* ===== Sprachumschalter DE | EN (zentriert) ===== */

/* DE|EN als flex-Zeile, br-Tags unterdrücken */
.pll-switcher-center {
    display: flex !important;
    flex-direction: row !important;
    align-items: center;
    gap: 6px;
    margin: 0; padding: 0;
}
.pll-switcher-center br { display: none !important; }

/* Sprachlinks */
.pll-switcher-center a,
.pll-switcher-center .pll-sep {
    font-size: 13px;
    font-weight: normal;
    color: #888;
    text-decoration: none;
    line-height: 1;
}

/* Aktive Sprache fett + orange */
html&#91;lang="de-DE"] .pll-link-de,
html&#91;lang="de"] .pll-link-de { font-weight: bold; color: #e8691e !important; }
html&#91;lang="en-US"] .pll-link-en,
html&#91;lang="en"] .pll-link-en { font-weight: bold; color: #e8691e !important; }

/* HTML 2 Widget absolut zentriert im Header */
.ast-header-html-2 {
    position: absolute !important;
    left: 50% !important;
    top: 50% !important;
    transform: translate(-50%, -50%) !important;
    z-index: 5;
    white-space: nowrap;
}
.site-primary-header-wrap { position: relative !important; }

/* Polylang-Menüeintrag ausblenden (ersetzt durch HTML 2) */
.lang-item { display: none !important; }
</code></pre>



<p><strong>Was diese CSS-Regeln bewirken – im Klartext:</strong></p>



<ul class="wp-block-list">
<li><code>.pll-switcher-center { display: flex }</code> – verhindert, dass die br-Tags DE und EN untereinander stapeln. Flex macht aus einer vertikalen Stapel eine horizontale Zeile.</li>



<li><code>html[lang="de-DE"] .pll-link-de</code> – erkennt die aktive Sprache anhand des <code>lang</code>-Attributs, das WordPress automatisch in den <code>&lt;html></code>-Tag schreibt. Kein JavaScript nötig.</li>



<li><code>.ast-header-html-2 { position: absolute }</code> – entnimmt das Widget seinem normalen Platz in der linken Zone und positioniert es exakt in der horizontalen und vertikalen Mitte des Headers. <code>translate(-50%, -50%)</code> korrigiert den Versatz durch den eigenen Elementabstand.</li>



<li><code>.lang-item { display: none }</code> – blendet den alten Polylang-Menüeintrag aus, der sonst noch „Deutsch&#8220; im rechten Menü anzeigen würde.</li>
</ul>



<p><strong>Bernd:</strong>&nbsp;„Position absolute? Das ist doch Hacks. Richtige Entwickler machen das nicht so.&#8220;<br><strong>Tanja:</strong>&nbsp;„Richtige Entwickler nehmen die Lösung, die funktioniert. Bei Astra Free ist das die einzige Option ohne kostenpflichtiges Upgrade.&#8220;<br><strong>Ulf:</strong>&nbsp;„Ist das wie wenn der Trainer taktisch improvisiert, weil der Mittelstürmer verletzt ist?&#8220;<br><strong>Tanja:</strong>&nbsp;„Perfekter Vergleich.&#8220;</p>



<p>Auf&nbsp;<strong>„Veröffentlichen&#8220;</strong>&nbsp;klicken.</p>



<h3 class="wp-block-heading">Schritt 14: Ergebnis prüfen</h3>



<p>Website aufrufen. Im Header sind jetzt drei Bereiche sichtbar:</p>



<ul class="wp-block-list">
<li><strong>Links:</strong> Logo</li>



<li><strong>Mitte:</strong> DE | EN (zentriert)</li>



<li><strong>Rechts:</strong> Hauptnavigation</li>
</ul>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400822080&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400822080" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="730" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/04/Bild-11-DEEN-zentriert-–-Vollansicht-1024x730.png" alt="Bild 10 - DE|EN zentriert – Vollansicht" class="wp-image-1697" srcset="https://www.foundic.org/wp-content/uploads/2026/04/Bild-11-DEEN-zentriert-–-Vollansicht-1024x730.png 1024w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-11-DEEN-zentriert-–-Vollansicht-300x214.png 300w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-11-DEEN-zentriert-–-Vollansicht-768x548.png 768w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-11-DEEN-zentriert-–-Vollansicht-1536x1095.png 1536w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-11-DEEN-zentriert-–-Vollansicht.png 1585w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 10 &#8211; DE|EN zentriert – Vollansicht</figcaption></figure>



<p>Das ist Variante B – dauerhaft sichtbar, sauber zentriert, optisch klar.</p>



<p><strong>Responsive prüfen – vollständige Lösung:</strong>&nbsp;Die absolute Positionierung funktioniert auf Desktop sehr gut, kann aber auf schmalen Viewports zu Überlappungen mit Logo oder Menü führen. Die empfohlene Lösung für Mobile:</p>



<p><strong>Desktop:</strong>&nbsp;HTML-Widget zentriert im Header (wie eingerichtet)<br><strong>Mobile:</strong>&nbsp;HTML-Widget ausblenden, nativen Polylang-Switcher im Off-Canvas-Menü verwenden</p>



<p>Dazu den Polylang-Menü-Switcher im Hauptmenü&nbsp;<strong>nicht</strong>&nbsp;entfernen, sondern nur auf Desktop ausblenden. CSS anpassen:</p>



<pre class="wp-block-code"><code>/* Desktop: Polylang-Menüeintrag ausblenden, HTML-Widget sichtbar */
.lang-item { display: none !important; }

/* Mobile: HTML-Widget ausblenden, Polylang-Menüeintrag wieder sichtbar */
@media (max-width: 768px) {
    .ast-header-html-2 { display: none !important; }
    /* Theme-Standarddarstellung des Menüeintrags wiederherstellen –
       je nach Theme kann hier list-item, block oder inherit passender sein */
    .lang-item { display: list-item !important; }
}
</code></pre>



<p>So hat der Nutzer auf jedem Gerät einen funktionierenden Sprachumschalter – auf Desktop zentriert und immer sichtbar, auf Mobile im Burger-Menü integriert. Die konkrete&nbsp;<code>display</code>-Eigenschaft kann je nach Theme-Menüstruktur variieren; im Zweifel mit den Browser-Entwicklertools prüfen, welcher Wert der Theme-Standard ist.</p>



<h2 class="wp-block-heading">Teil 5: Englisches Menü einrichten</h2>



<p>Der Sprachumschalter ist da. Aber wenn jemand auf EN klickt und zur englischen Startseite wechselt, sieht er noch immer „KI-News&#8220;, „Themen&#8220;, „Projekte&#8220;, „Schulungen&#8220;. Das ist wie ein internationales Hotel, das englische Gäste empfängt – und ihnen dann die Speisekarte auf Deutsch gibt.</p>



<p>Das ändern wir jetzt.</p>



<p><strong>Ulf:</strong>&nbsp;„Warte, muss ich jetzt alle meine Artikel auf Englisch schreiben?&#8220;<br><strong>Tanja:</strong>&nbsp;„Nein. Erst kommt die technische Struktur – Kategorien, Menüs. Die Artikel kommen danach Schritt für Schritt.&#8220;<br><strong>Bernd:</strong>&nbsp;„Ich würde Google Translate drüber laufen lassen. Fertig.&#8220;<br><strong>Tanja:</strong>&nbsp;„Bernd, das hat Stiftung Warentest schon für Websites gemacht. Das Ergebnis war erschreckend.&#8220;</p>



<h3 class="wp-block-heading">Schritt 15: Kategorien übersetzen</h3>



<p>Im Backend:&nbsp;<strong>Beiträge → Kategorien</strong><br>Polylang hat jetzt neben jeder Kategorie ein kleines Flaggen-Symbol hinzugefügt. Für jede Kategorie die englische Übersetzung anlegen:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Deutsch</th><th>Englisch</th></tr></thead><tbody><tr><td>KI-News</td><td>AI News</td></tr><tr><td>Themen</td><td>Topics</td></tr><tr><td>Projekte</td><td>Projects</td></tr><tr><td>Schulungen</td><td>Training</td></tr></tbody></table></figure>



<p>Auf das 🇺🇸-Symbol neben einer Kategorie klicken → Editor öffnet sich → englischen Namen eingeben → speichern.</p>



<h3 class="wp-block-heading">Schritt 16: Permalinks neu speichern</h3>



<p>Das ist einer der Schritte, die aussehen als würden sie nichts tun – und trotzdem unverzichtbar sind.</p>



<p><strong>Wichtig:</strong>&nbsp;Nach der Kategorien-Übersetzung müssen die Permalinks neu gespeichert werden, damit Polylang die Rewrite-Regeln für&nbsp;<code>/en/</code>&nbsp;korrekt registriert.</p>



<p>Im Backend:&nbsp;<strong>Einstellungen → Permalinks → „Änderungen speichern&#8220;</strong>&nbsp;klicken.</p>



<p>Kein Wert muss geändert werden – der Klick alleine reicht. Was passiert im Hintergrund? WordPress schreibt die URL-Muster neu – jetzt weiß der Server, dass Anfragen auf&nbsp;<code>/en/</code>&nbsp;zu Polylang weitergeleitet werden sollen und nicht als 404-Fehler enden.</p>



<p>Nach dem Speichern ist die englische Startseite unter&nbsp;<code>deine-domain.de/en/</code>&nbsp;erreichbar. Der Inhalt ist zunächst leer – das ist normal, da noch keine englischen Beiträge vorhanden sind:</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400822a04&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400822a04" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="723" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/04/Bild-12-EN-Seite-nach-Permalink-Fix-1024x723.png" alt="Bild 11 - EN-Seite nach Permalink-Fix" class="wp-image-1699" srcset="https://www.foundic.org/wp-content/uploads/2026/04/Bild-12-EN-Seite-nach-Permalink-Fix-1024x723.png 1024w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-12-EN-Seite-nach-Permalink-Fix-300x212.png 300w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-12-EN-Seite-nach-Permalink-Fix-768x542.png 768w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-12-EN-Seite-nach-Permalink-Fix-1536x1085.png 1536w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-12-EN-Seite-nach-Permalink-Fix-2048x1446.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 11 &#8211; EN-Seite nach Permalink-Fix</figcaption></figure>



<h3 class="wp-block-heading">Schritt 17: Englisches Menü „Main Menu&#8220; erstellen</h3>



<p>Im Backend:&nbsp;<strong>Design → Menüs</strong>&nbsp;→ Link&nbsp;<strong>„erstelle ein neues Menü&#8220;</strong>&nbsp;klicken.</p>



<ul class="wp-block-list">
<li>Name: <code>Main Menu</code></li>



<li>Position im Theme: ☑ <strong>Primäres Menü English</strong>, ☑ <strong>Off-Canvas-Menü English</strong></li>



<li>Gleichzeitig diese Positionen beim deutschen Hauptmenü <strong>abhaken</strong> – sonst erscheint das englische Menü auch auf der deutschen Seite<br>Auf <strong>„Menü erstellen&#8220;</strong> klicken.</li>
</ul>



<h3 class="wp-block-heading">Schritt 23: Englische Kategorien zum Main Menu hinzufügen</h3>



<p>Im Bereich „Menüeinträge hinzufügen&#8220; →&nbsp;<strong>Kategorien</strong>&nbsp;→ Tab&nbsp;<strong>„Alle anzeigen&#8220;</strong>.</p>



<p>Folgende vier englischen Kategorien anhaken:</p>



<ul class="wp-block-list">
<li>☑ AI News</li>



<li>☑ Projects</li>



<li>☑ Topics</li>



<li>☑ Training</li>
</ul>



<p>Auf&nbsp;<strong>„Zum Menü hinzufügen&#8220;</strong>&nbsp;→&nbsp;<strong>„Menü speichern&#8220;</strong>&nbsp;klicken.</p>



<h3 class="wp-block-heading">Schritt 24: Ergebnis – beide Sprachen mit eigenen Menüs</h3>



<p>Jetzt hat die Website zwei vollständig getrennte Navigationsbereiche.<br><strong>Englische Seite</strong>&nbsp;(<code>deine-domain.de/en/</code>): DE |&nbsp;<strong>EN</strong>&nbsp;· AI News · Projects · Topics · Training</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400823139&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400823139" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="71" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/04/Bild-13-EN-Header-mit-englischem-Menue-1024x71.png" alt="Bild 12 - EN Header mit englischem Menü" class="wp-image-1701" srcset="https://www.foundic.org/wp-content/uploads/2026/04/Bild-13-EN-Header-mit-englischem-Menue-1024x71.png 1024w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-13-EN-Header-mit-englischem-Menue-300x21.png 300w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-13-EN-Header-mit-englischem-Menue-768x53.png 768w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-13-EN-Header-mit-englischem-Menue-1536x107.png 1536w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-13-EN-Header-mit-englischem-Menue-2048x142.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 12 &#8211; EN Header mit englischem Menü</figcaption></figure>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Sprache</th><th>URL</th><th>Menüpunkte</th></tr></thead><tbody><tr><td>Deutsch</td><td><code>deine-domain.de/</code></td><td>KI-News · Themen · Projekte · Schulungen</td></tr><tr><td>Englisch</td><td><code>deine-domain.de/en/</code></td><td>AI News · Projects · Topics · Training</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Teil 6: Browsersprache-Erkennung einrichten</h2>



<p>Bisher muss der Besucher selbst auf DE oder EN klicken. Das ist okay. Aber noch besser wäre es, wenn die Website schon beim ersten Besuch automatisch die richtige Sprache zeigt – basierend auf der Browsersprache des Nutzers.</p>



<p><strong>Ulf:</strong>&nbsp;„Wie weiß die Website, welche Sprache mein Browser hat?&#8220;<br><strong>Tanja:</strong>&nbsp;„Jeder Browser schickt beim Seitenaufruf einen sogenannten Header mit – darin steht die bevorzugte Sprache. Polylang liest das aus und leitet entsprechend weiter.&#8220;<br><strong>Bernd:</strong>&nbsp;„Ich hab das einfach über JavaScript gemacht. Hat nicht funktioniert.&#8220;<br><strong>Tanja:</strong>&nbsp;„Weil du dann einen gecachten Redirect hattest. Das ist ein Klassiker.&#8220;</p>



<h3 class="wp-block-heading">Schritt 18: Polylang-Einstellung aktivieren</h3>



<p>Im Backend:&nbsp;<strong>Polylang → Einstellungen</strong>&nbsp;→ Funktion&nbsp;<strong>„Browsersprache erkennen&#8220;</strong>&nbsp;aktivieren.<br>Was passiert: Polylang liest beim ersten Besuch der Startseite den&nbsp;<code>Accept-Language</code>-Header des Browsers und leitet auf die passende Sprachversion weiter. Nur beim ersten Besuch – danach merkt sich ein Cookie die Wahl des Nutzers.</p>



<h3 class="wp-block-heading">Schritt 19: WP Fastest Cache – Startseite ausschließen</h3>



<p>Hier lauert eine unsichtbare Falle – Bernd ist direkt reingetappt.<br><strong>Problem:</strong>&nbsp;WP Fastest Cache speichert die Startseite als statische HTML-Datei. Wird diese gecachte Datei direkt ausgeliefert, läuft kein PHP mehr. Die Polylang-Umleitung ist aber PHP-Code – sie wird also nie ausgeführt. Alle Besucher sehen immer die Standardsprache.<br><strong>Lösung:</strong>&nbsp;Im Plugin&nbsp;<strong>WP Fastest Cache → Tab „Ausschließen&#8220;</strong>&nbsp;eine Regel für die Startseite anlegen:</p>



<ul class="wp-block-list">
<li>Regel: <strong>„Homepage&#8220;</strong> → „The homepage has been excluded&#8220;<br>Anschließend alle Caches leeren: <strong>WP Fastest Cache → Alle Caches löschen</strong>.<br><strong>Gilt auch für andere Caching-Plugins:</strong> Jedes Caching-Plugin, das statische HTML-Dateien erzeugt, muss für die Startseite deaktiviert werden. Andernfalls funktioniert die Browsersprache-Erkennung nicht.</li>
</ul>



<h3 class="wp-block-heading">Schritt 20: Fallback für nicht-deutsche Sprachen (PHP-Snippet)</h3>



<p>Noch ein Feinschliff: Polylang leitet standardmäßig nur dann weiter, wenn die Browser-Sprache exakt einer Website-Sprache entspricht. Ein Besucher mit französischem Browser würde daher auf Deutsch (= Standardsprache) landen – nicht auf Englisch.<br>Für die meisten internationalen Websites ist Englisch aber der sinnvolle Fallback für alle Nicht-DE-Sprachen. Dafür gibt es ein kleines PHP-Snippet.<br><strong>Einrichtung über das Plugin „Code Snippets&#8220;</strong>&nbsp;(sicherer als functions.php – dazu mehr in Teil 8):</p>



<ol class="wp-block-list">
<li>Plugin installieren: <strong>Plugins → Plugin hinzufügen → „Code Snippets&#8220;</strong> suchen und installieren</li>



<li>Im Backend: <strong>Snippets → Neu hinzufügen</strong></li>



<li>Einstellungen:
<ul class="wp-block-list">
<li><strong>Titel:</strong> Polylang: Nicht erkannte Browsersprachen auf Englisch umleiten</li>



<li><strong>Typ:</strong> PHP</li>



<li><strong>Location:</strong> Nur im Frontend ausführen</li>
</ul>
</li>



<li>Folgenden Code einfügen:</li>
</ol>



<pre class="wp-block-code"><code>add_filter( 'pll_preferred_language', 'foundic_language_fallback' );
function foundic_language_fallback( $slug ) {
    if ( false === $slug ) {
        return 'en';
    }
    return $slug;
}
</code></pre>



<ol start="5" class="wp-block-list">
<li>Snippet aktivieren und speichern</li>
</ol>



<p><strong>Was macht dieser Code?</strong>&nbsp;Polylang übergibt der Filterfunktion die erkannte Browsersprache. Wenn keine passende Sprache gefunden wurde, liefert Polylang&nbsp;<code>false</code>. Das Snippet fängt genau diesen Fall ab und gibt stattdessen&nbsp;<code>'en'</code>&nbsp;zurück – Englisch also.<br><strong>Ergebnis:</strong></p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Browser-Sprache</th><th>Verhalten</th></tr></thead><tbody><tr><td><code>de</code>,&nbsp;<code>de-DE</code>,&nbsp;<code>de-AT</code></td><td>→ Startseite Deutsch ✅</td></tr><tr><td><code>en</code>,&nbsp;<code>en-US</code>,&nbsp;<code>en-GB</code></td><td>→ Startseite Englisch ✅</td></tr><tr><td><code>fr</code>,&nbsp;<code>es</code>,&nbsp;<code>it</code>,&nbsp;<code>zh</code>, …</td><td>→ Startseite Englisch (Fallback) ✅</td></tr></tbody></table></figure>



<p><strong>Hinweis:</strong>&nbsp;Gilt nur für Erstbesucher ohne gesetztes&nbsp;<code>pll_language</code>-Cookie. Rückkehrer behalten ihre zuletzt gewählte Sprache. Eingeloggte Admins werden nie umgeleitet.</p>



<p><strong>Das solltest du bedenken:</strong>&nbsp;Der Fallback auf Englisch für alle Nicht-DE-Sprachen ist eine&nbsp;<strong>Produktentscheidung</strong>, keine technische Notwendigkeit. Überleg dir, ob das für deine Zielgruppe sinnvoll ist – für eine deutschsprachige Community-Seite z.B. könnte Deutsch als Fallback besser passen. Außerdem: Browser-Sprache und Nutzerpräferenz sind nicht immer gleich. Wer einen deutschen Browser hat, aber Englisch bevorzugt, landet trotzdem auf Deutsch. Und bei aggressiven Redirect-Setups können Suchmaschinen-Crawler und CDN-Systeme unerwartetes Verhalten zeigen – prüfe nach der Aktivierung, ob Google Search Console keine Crawling-Fehler meldet.</p>



<p><strong>Empfehlung:</strong>&nbsp;Für den Anfang lieber&nbsp;<strong>ohne Browsersprache-Redirect live gehen</strong>. Baue erst Inhalte in beiden Sprachen auf, teste den Switcher manuell und aktiviere die automatische Erkennung erst danach. Für kleine Blogs oder Community-Seiten mit klarer deutschsprachiger Zielgruppe ist die Browserweiterleitung oft gar nicht nötig. Für internationale SEO-Setups mit Google-Traffic aus mehreren Ländern kann sie sinnvoll sein – dann aber unbedingt mit&nbsp;<code>curl</code>-Test und Search-Console-Monitoring einrichten.</p>



<h2 class="wp-block-heading">Teil 7: Inhalte auf Englisch übersetzen</h2>



<p>Die technische Einrichtung ist jetzt vollständig abgeschlossen. Tanja lehnt sich zurück. Ulf sieht aus als hätte er gerade ein Tor geschossen. Bernd hat still seinen Kaffee getrunken.</p>



<p><strong>Ulf:</strong>&nbsp;„Und jetzt?&#8220;<br><strong>Tanja:</strong>&nbsp;„Jetzt kommt die Arbeit.&#8220;<br><strong>Bernd:</strong>&nbsp;„Kann man das nicht automatisch übersetzen lassen?&#8220;<br><strong>Tanja:</strong>&nbsp;„Kann man. Sollte man bei Fachtexten nicht. Aber das ist deine Entscheidung.&#8220;</p>



<h3 class="wp-block-heading">Artikel übersetzen</h3>



<ol class="wp-block-list">
<li>Einen Beitrag im Backend öffnen: <strong>Beiträge → Alle Beiträge</strong></li>



<li>Rechts in der Sidebar erscheint das Polylang-Feld <strong>„Sprachen&#8220;</strong></li>



<li>Neben dem 🇺🇸-Symbol auf <strong>„+&#8220;</strong> klicken</li>



<li>Es öffnet sich ein neuer Editor für die englische Version</li>



<li>Den Artikel auf Englisch verfassen und veröffentlichen</li>
</ol>



<p>Polylang verknüpft beide Versionen automatisch und setzt die korrekten&nbsp;<strong>hreflang-Tags</strong>&nbsp;für Google – das sind Hinweise im Seitenquelltext, die Google sagen: „Diese Seite existiert auch auf Englisch, und hier ist der Link.&#8220; Wichtig für internationale SEO.</p>



<h3 class="wp-block-heading">Seiten übersetzen</h3>



<p>Für Seiten (Impressum, Datenschutz, etc.) funktioniert es genauso:&nbsp;<strong>Seiten → Alle Seiten → gewünschte Seite öffnen → 🇺🇸 → „+&#8220;</strong>.</p>



<p><strong>Tipp:</strong>&nbsp;Übersetze zuerst die rechtlich relevanten Seiten (Impressum, Datenschutz, Cookie-Richtlinie), bevor du die eigentlichen Artikel angehst.</p>



<p><strong>Rechtlicher Hinweis:</strong>&nbsp;Eine sprachliche Übersetzung dieser Seiten ersetzt keine rechtliche Prüfung für andere Zielmärkte. Je nach Land können abweichende Anforderungen gelten – etwa andere Pflichtangaben im Impressum oder zusätzliche Datenschutzregelungen. Im Zweifel rechtlichen Rat einholen.</p>



<h2 class="wp-block-heading">Teil 8: Fehlerbehebung</h2>



<p>Tanja stellt eine Tasse Kaffee auf den Tisch. „Jetzt kommen die Dinge, die ich schon erlebt habe. Und Bernd auch.&#8220;</p>



<p>In diesem Kapitel sind die häufigsten Probleme bei der Polylang-Einrichtung und ihre Lösungen dokumentiert. Die Fehler sind nach Häufigkeit und Schwere gegliedert.</p>



<h3 class="wp-block-heading">Häufige Fehler</h3>



<h4 class="wp-block-heading">Fehler 1: EN-Link im Sprachumschalter fehlt</h4>



<p><strong>Symptom:</strong>&nbsp;Im Menü erscheint nur Deutsch, der EN-Link ist unsichtbar.<br><strong>Ursache:</strong>&nbsp;Polylang-Standardverhalten – EN wird nur angezeigt, wenn für die aktuelle Seite eine englische Übersetzung existiert.<br><strong>Lösung:</strong>&nbsp;HTML-2-Widget im Astra Header Builder verwenden (→ Schritt 15–18).</p>



<h3 class="wp-block-heading">Fehler 2: 404-Fehler auf&nbsp;<code>/en/</code></h3>



<p><strong>Symptom:</strong>&nbsp;Die englische Startseite&nbsp;<code>deine-domain.de/en/</code>&nbsp;zeigt eine 404-Fehlerseite.<br><strong>Ursache:</strong>&nbsp;Polylang hat die Rewrite-Regeln noch nicht registriert.<br><strong>Lösung:</strong>&nbsp;Im Backend&nbsp;<strong>Einstellungen → Permalinks → „Änderungen speichern&#8220;</strong>&nbsp;klicken. Kein Inhalt muss geändert werden – der Klick alleine reicht, um die Rewrite-Regeln neu zu schreiben.</p>



<h4 class="wp-block-heading">Fehler 3: Englische Seite hat kein Menü</h4>



<p><strong>Symptom:</strong>&nbsp;Auf der&nbsp;<code>/en/</code>-Startseite fehlt die Navigationsleiste komplett.<br><strong>Ursache:</strong>&nbsp;Das englische Menü wurde noch nicht den richtigen Theme-Positionen zugewiesen.<br><strong>Lösung:</strong>&nbsp;Im Backend&nbsp;<strong>Design → Menüs → Tab „Positionen verwalten&#8220;</strong>:</p>



<ul class="wp-block-list">
<li><strong>Primäres Menü English</strong> → Main Menu zuweisen</li>



<li><strong>Off-Canvas-Menü English</strong> → Main Menu zuweisen</li>
</ul>



<h3 class="wp-block-heading">Layout-Fehler</h3>



<h4 class="wp-block-heading">Fehler 4: Sprachumschalter im Header nicht sichtbar (Astra Grid-Problem)</h4>



<p><strong>Symptom:</strong>&nbsp;Der Sprachumschalter ist im Header-Builder eingebaut, aber im Frontend unsichtbar.<br><strong>Ursache:</strong>&nbsp;Astra berechnet die Spaltenbreiten dynamisch. Die Mittelspalte kann dabei 0px Breite bekommen – alles darin ist unsichtbar. Das passiert, wenn Astra erkennt, dass die Mittelspalte leer ist, und ihr schlicht keinen Platz zuweist.<br><strong>Diagnose:</strong>&nbsp;In der Browser-Konsole (F12) prüfen:</p>



<pre class="wp-block-code"><code>const header = document.querySelector('.ast-primary-header-bar .ast-builder-grid-row-has-sides');
getComputedStyle(header).gridTemplateColumns;
// Falls Ergebnis: "639.5px 0px 639.5px" → Problem bestätigt
</code></pre>



<p><strong>Lösung:</strong>&nbsp;CSS-Override im Customizer → Zusätzliches CSS hinzufügen:</p>



<pre class="wp-block-code"><code>/* Sprachumschalter: Center-Spalte sichtbar machen */
.ast-primary-header-bar .ast-builder-grid-row-has-sides.ast-grid-center-col-layout {
  grid-template-columns: 1fr auto 1fr !important;
}
.ast-primary-header-bar .site-header-primary-section-center {
  min-width: 80px !important;
  overflow: visible !important;
}
</code></pre>



<h3 class="wp-block-heading">Fehler 5: Polylang blendet Sprachumschalter per CSS aus</h3>



<p><strong>Symptom:</strong>&nbsp;Der Sprachumschalter ist im Quellcode vorhanden, aber im Browser nicht sichtbar.<br><strong>Ursache:</strong>&nbsp;Polylang fügt standardmäßig die CSS-Regel&nbsp;<code>.lang-item { display: none }</code>&nbsp;ein und macht die Items normalerweise per JavaScript wieder sichtbar. In manchen Theme-Setups greift dieses JavaScript nicht – und alles bleibt ausgeblendet.<br><strong>Diagnose:</strong>&nbsp;In der Browser-Konsole prüfen:</p>



<pre class="wp-block-code"><code>// Sucht nach der problematischen Regel in allen Stylesheets
&#91;...document.styleSheets].forEach(s =&gt; {
  try { &#91;...s.cssRules].forEach(r =&gt; {
    if (r.selectorText &amp;&amp; r.selectorText.includes('lang-item')) console.log(r.cssText);
  }); } catch(e) {}
});
</code></pre>



<p><strong>Lösung:</strong>&nbsp;Das CSS im Customizer (Schritt 18) setzt&nbsp;<code>.lang-item { display: none !important; }</code>&nbsp;und verwendet stattdessen das eigene HTML-2-Widget, das nicht von Polylang-CSS beeinflusst wird.</p>



<h3 class="wp-block-heading">Kritische Fehler</h3>



<h4 class="wp-block-heading">Fehler 6: PHP-Syntaxfehler / Website offline</h4>



<p>Das ist Bernds Spezialität.</p>



<p><strong>Bernd:</strong>&nbsp;„Ich hab mal schnell was in die functions.php geschrieben. Dann war die Seite weg.&#8220;<br><strong>Tanja:</strong>&nbsp;„Wie lange?&#8220;<br><strong>Bernd:</strong>&nbsp;„&#8230;eine Stunde.&#8220;<br><strong>Ulf:</strong>&nbsp;„Eine Stunde! Das ist ein kompletter Halbzeitausfall.&#8220;</p>



<p><strong>Symptom:</strong>&nbsp;Nach einer Änderung in&nbsp;<code>functions.php</code>&nbsp;zeigt die Website nur einen weißen Bildschirm oder einen HTTP 500-Fehler. Das WordPress-Backend ist nicht mehr erreichbar.<br><strong>Ursache:</strong>&nbsp;Ein PHP-Syntaxfehler in&nbsp;<code>functions.php</code>&nbsp;bringt WordPress komplett zum Absturz. WordPress prüft den Code nicht vor dem Speichern – es speichert einfach, auch wenn der Code kaputt ist.<br><strong>Lösung A: Über das Hosting-Backup wiederherstellen (empfohlen)</strong></p>



<p>Die meisten Hosting-Anbieter haben eine Backup-Funktion. Bei Strato z.B.:</p>



<ol class="wp-block-list">
<li>Strato Kundencenter → <strong>BackupControl</strong></li>



<li>Letztes Backup vor der Änderung auswählen</li>



<li>Zu <code>/wp-content/themes/dein-theme/</code> navigieren</li>



<li><code>functions.php</code> mit dem Symbol ≠ (= Unterschied zum Backup) markieren</li>



<li><strong>„Auswahl wiederherstellen&#8220;</strong> → Bestätigen<br>Nach der Wiederherstellung ist die Website sofort wieder online:</li>
</ol>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e44008242b5&quot;}" data-wp-interactive="core/image" data-wp-key="69e44008242b5" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="71" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/04/Bild-13-EN-Header-mit-englischem-Menue-1-1024x71.png" alt="Bild 13 - EN Header mit englischem Menü" class="wp-image-1703" srcset="https://www.foundic.org/wp-content/uploads/2026/04/Bild-13-EN-Header-mit-englischem-Menue-1-1024x71.png 1024w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-13-EN-Header-mit-englischem-Menue-1-300x21.png 300w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-13-EN-Header-mit-englischem-Menue-1-768x53.png 768w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-13-EN-Header-mit-englischem-Menue-1-1536x107.png 1536w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-13-EN-Header-mit-englischem-Menue-1-2048x142.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 13 &#8211; EN Header mit englischem Menü</figcaption></figure>



<p>Und die&nbsp;<code>functions.php</code>&nbsp;ist wieder im sauberen Ausgangszustand:</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440082486d&quot;}" data-wp-interactive="core/image" data-wp-key="69e440082486d" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="723" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/04/Bild-14-functions.php-wiederhergestellt-1024x723.png" alt="Bild 14 - functions.php wiederhergestellt" class="wp-image-1705" srcset="https://www.foundic.org/wp-content/uploads/2026/04/Bild-14-functions.php-wiederhergestellt-1024x723.png 1024w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-14-functions.php-wiederhergestellt-300x212.png 300w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-14-functions.php-wiederhergestellt-768x542.png 768w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-14-functions.php-wiederhergestellt-1536x1085.png 1536w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-14-functions.php-wiederhergestellt.png 1600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 14 &#8211; functions.php wiederhergestellt</figcaption></figure>



<p><strong>Lösung B: Über FTP/SFTP manuell wiederherstellen</strong></p>



<ol class="wp-block-list">
<li>Mit einem FTP-Programm (z.B. FileZilla) verbinden</li>



<li>Datei <code>/wp-content/themes/dein-theme/functions.php</code> herunterladen</li>



<li>In einem Text-Editor öffnen und den fehlerhaften Code entfernen</li>



<li>Datei wieder hochladen und überschreiben<br><strong>Prävention:</strong> Niemals <code>functions.php</code> direkt im WordPress-Theme-Editor bearbeiten. Stattdessen das Plugin <strong>„Code Snippets&#8220;</strong> verwenden (→ Schritt 27) – es validiert Code vor der Aktivierung und kann einzelne Snippets deaktivieren, ohne die gesamte Website zu zerstören.</li>
</ol>



<h4 class="wp-block-heading">Fehler 7: Änderungen im Frontend nicht sichtbar (Cache-Problem)</h4>



<p><strong>Symptom:</strong>&nbsp;CSS-Änderungen oder Menü-Updates sind im Frontend nicht sichtbar, obwohl sie im Backend gespeichert wurden.<br><strong>Ursache:</strong>&nbsp;Ein Caching-Plugin liefert noch die alte, gecachte Version aus. Das Caching-Plugin weiß nicht, dass du etwas geändert hast – es serviert einfach die gespeicherte Version.<br><strong>Lösung:</strong>&nbsp;Nach jeder Änderung an CSS, Menüs oder Theme-Einstellungen den Cache leeren:</p>



<ul class="wp-block-list">
<li>In der WordPress-Adminleiste auf <strong>„WP Fastest Cache&#8220;</strong> klicken</li>



<li><strong>„Alle Caches löschen&#8220;</strong> auswählen<br><strong>Tipp:</strong> Wenn du Änderungen direkt im Customizer machst, immer zuerst auf <strong>„Veröffentlichen&#8220;</strong> klicken und erst dann den Cache leeren. Die Reihenfolge ist wichtig.</li>
</ul>



<h4 class="wp-block-heading">Fehler 8: Browsersprache-Erkennung funktioniert nicht</h4>



<p><strong>Symptom:</strong>&nbsp;Englischsprachige Besucher landen trotz aktivierter Browsersprache-Erkennung immer auf der deutschen Seite.<br><strong>Häufige Ursachen und Lösungen:</strong></p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Ursache</th><th>Lösung</th></tr></thead><tbody><tr><td>Startseite ist gecacht</td><td>Startseite im Caching-Plugin ausschließen (→ Schritt 26)</td></tr><tr><td>Eingeloggter Admin</td><td>Admins werden von Polylang nie umgeleitet – normales Verhalten</td></tr><tr><td>Cookie bereits gesetzt</td><td><code>pll_language</code>-Cookie löschen und erneut testen</td></tr><tr><td>Polylang-Einstellung deaktiviert</td><td><strong>Polylang → Einstellungen → „Browsersprache erkennen&#8220;</strong>&nbsp;prüfen</td></tr></tbody></table></figure>



<p><strong>Test-Tipp:</strong>&nbsp;Ein echter Test ist nur mit einem Browser möglich, der auf&nbsp;<code>en</code>&nbsp;eingestellt ist, oder via Terminal:</p>



<pre class="wp-block-code"><code>curl -H "Accept-Language: en" https://deine-domain.de/ -I
</code></pre>



<p>Du solltest einen Redirect auf&nbsp;<code>/en/</code>&nbsp;sehen.</p>



<h3 class="wp-block-heading">Endergebnis: Funktionstest DE ↔ EN</h3>



<p>Der folgende Test zeigt das Ergebnis mit dem&nbsp;<strong>nativen Polylang-Menü-Switcher</strong>&nbsp;(Variante A), der artikelgenau auf die jeweilige Übersetzung verlinkt:</p>



<p><strong>Auf dem deutschen Artikel:</strong>&nbsp;DE | EN – Klick auf EN führt direkt zur englischen Version</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e44008250b6&quot;}" data-wp-interactive="core/image" data-wp-key="69e44008250b6" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="97" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/04/Bild-16-DE-Artikel-mit-korrektem-EN-Link-1024x97.png" alt="Bild 15 - DE-Artikel mit korrektem EN-Link" class="wp-image-1707" srcset="https://www.foundic.org/wp-content/uploads/2026/04/Bild-16-DE-Artikel-mit-korrektem-EN-Link-1024x97.png 1024w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-16-DE-Artikel-mit-korrektem-EN-Link-300x28.png 300w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-16-DE-Artikel-mit-korrektem-EN-Link-768x73.png 768w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-16-DE-Artikel-mit-korrektem-EN-Link-1536x145.png 1536w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-16-DE-Artikel-mit-korrektem-EN-Link-2048x194.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 15 &#8211; DE-Artikel mit korrektem EN-Link</figcaption></figure>



<p><strong>Nach dem Wechsel auf EN:</strong>&nbsp;Englisches Menü, EN fett/orange, zurück zu DE funktioniert ebenfalls</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400825662&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400825662" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="97" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/04/Bild-17-EN-Artikel-nach-Sprachumschaltung-1024x97.png" alt="Bild 16 - EN-Artikel nach Sprachumschaltung" class="wp-image-1708" srcset="https://www.foundic.org/wp-content/uploads/2026/04/Bild-17-EN-Artikel-nach-Sprachumschaltung-1024x97.png 1024w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-17-EN-Artikel-nach-Sprachumschaltung-300x28.png 300w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-17-EN-Artikel-nach-Sprachumschaltung-768x73.png 768w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-17-EN-Artikel-nach-Sprachumschaltung-1536x145.png 1536w, https://www.foundic.org/wp-content/uploads/2026/04/Bild-17-EN-Artikel-nach-Sprachumschaltung-2048x194.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 16 &#8211; EN-Artikel nach Sprachumschaltung</figcaption></figure>



<p><strong>Hinweis für Variante B (HTML-Widget):</strong>&nbsp;Der statische HTML-Switcher im Header zeigt auf Unterseiten immer auf die jeweilige Sprach-Startseite, nicht auf den übersetzten Artikel. Artikelgenaues Umschalten ist mit Variante B nur möglich, wenn zusätzlich der native Polylang-Switcher im Menü aktiv bleibt.</p>



<h2 class="wp-block-heading">Teil 9: Wartung und spätere Änderungen</h2>



<p>Tanja schaut in die Runde. „Ihr denkt, das war&#8217;s?&#8220;</p>



<p>Es ist nie wirklich fertig. Websites wachsen, Themes ändern sich, neue Sprachen kommen hinzu. Hier sind die häufigsten Wartungsszenarien – damit du nicht wieder von vorne anfangen musst.</p>



<p><strong>Dritte Sprache hinzufügen:</strong>&nbsp;In Polylang → Sprachen eine neue Sprache anlegen, ein neues Menü für diese Sprache erstellen und das HTML-Widget im Header um einen dritten Link ergänzen. CSS für&nbsp;<code>.pll-link-xx</code>&nbsp;entsprechend erweitern.</p>



<p><strong>Theme-Wechsel:</strong>&nbsp;Das HTML-Widget und das zusätzliche CSS bleiben erhalten (sie liegen im Customizer, nicht im Theme). Prüfe nach dem Theme-Wechsel, ob die CSS-Selektoren&nbsp;<code>.ast-header-html-2</code>&nbsp;und&nbsp;<code>.site-primary-header-wrap</code>&nbsp;noch greifen – diese sind Astra-spezifisch und müssen für andere Themes angepasst werden.</p>



<p><strong>Wechsel von Astra Free zu Astra Pro:</strong>&nbsp;Astra Pro bietet einen echten Header Builder mit freier Positionierung. Das HTML-Widget und die absolute CSS-Positionierung können dann entfernt werden – stattdessen den nativen Polylang-Switcher direkt im Header-Builder platzieren.</p>



<p><strong>Wechsel des Caching-Plugins:</strong>&nbsp;Die Ausnahme für die Startseite (→ Schritt 26) muss im neuen Plugin neu eingerichtet werden. Andernfalls funktioniert die Browsersprache-Erkennung nicht.</p>



<p><strong>Migration auf Staging und zurück:</strong>&nbsp;Die Domain-URLs im HTML-Widget müssen auf der Staging-Umgebung angepasst werden. Am einfachsten: Widget auf Staging temporär deaktivieren und nur den nativen Polylang-Switcher nutzen.</p>



<h2 class="wp-block-heading">Teil 10: Rückbau / Deaktivierung</h2>



<p>Manchmal will man einen Schritt zurückgehen. Kein Problem – hier ist der saubere Rückweg.</p>



<p><strong>HTML-Widget entfernen:</strong>&nbsp;Design → Customizer → Header Builder → HTML-2-Widget aus dem Header ziehen oder löschen.</p>



<p><strong>Nativen Polylang-Switcher reaktivieren:</strong>&nbsp;Design → Menüs → Hauptmenü → Sprachumschalter-Eintrag aufklappen → gewünschte Einstellungen setzen. Im CSS den Block&nbsp;<code>.lang-item { display: none !important; }</code>&nbsp;entfernen.</p>



<p><strong>CSS aufräumen:</strong>&nbsp;Im Customizer → Zusätzliches CSS den gesamten Block zwischen&nbsp;<code>/* ===== Sprachumschalter DE | EN ===== */</code>&nbsp;und dem letzten&nbsp;<code>}</code>&nbsp;löschen. Der restliche CSS-Code der Website bleibt unberührt.</p>



<p><strong>Menüs zurücksetzen:</strong>&nbsp;Design → Menüs → Tab „Positionen verwalten&#8220; → Primäres Menü English und Off-Canvas-Menü English auf „kein Menü&#8220; setzen, falls gewünscht.</p>



<p><strong>Polylang deaktivieren:</strong>&nbsp;Plugins → Polylang → Deaktivieren. Bestehende Übersetzungsverknüpfungen bleiben in der Datenbank erhalten, sind aber ohne Polylang inaktiv. Alle Beiträge bleiben zugänglich – sie verlieren nur ihre Sprachzuordnung.</p>



<h2 class="wp-block-heading">Teil 11: Hinweis für Entwickler – Variante C</h2>



<p>Der HTML-Widget-Ansatz in Variante B ist ein pragmatischer Workaround für Astra Free. Für produktive Websites mit längerfristiger Wartung ist eine dynamische Lösung robuster.</p>



<p><strong>Tanja:</strong>&nbsp;„Für Entwickler gibt es eine elegantere Lösung.&#8220;<br><strong>Bernd:</strong>&nbsp;„Ich bin quasi auch Entwickler.&#8220;<br><strong>Tanja:</strong>&nbsp;„Bernd, du hast functions.php mit Notepad bearbeitet.&#8220;<br><strong>Bernd:</strong>&nbsp;„Das ist ein valider Editor.&#8220;<br><strong>Tanja:</strong>&nbsp;„Ich rede weiter.&#8220;</p>



<p>Eine technisch robustere Alternative ist ein dynamischer Sprachumschalter, der über einen passenden Theme-Hook, einen Template-Part oder einen Shortcode eingebunden wird.</p>



<p><strong>Beispiel: Shortcode</strong></p>



<pre class="wp-block-code"><code>// In einem Child-Theme oder per Code-Snippets-Plugin:
add_shortcode( 'sprachumschalter', function() {
    if ( ! function_exists( 'pll_the_languages' ) ) return '';
    ob_start();
    pll_the_languages( array(
        'show_flags'          =&gt; 0,
        'show_names'          =&gt; 0,
        'display_names_as'    =&gt; 'slug',
        'hide_current'        =&gt; 0,
        'hide_if_no_translation' =&gt; 0,
    ) );
    return ob_get_clean();
} );
</code></pre>



<p>Der Shortcode&nbsp;<code>[sprachumschalter]</code>&nbsp;kann dann in einem Widget, einem Template-Part oder direkt im Header-Markup platziert werden. Polylang rendert dabei dynamisch die korrekten URLs – auf Artikelseiten zeigt der Switcher direkt auf die verknüpfte Übersetzung, nicht auf die Startseite.<br><strong>Ausgabeformat:</strong>&nbsp;<code>pll_the_languages()</code>&nbsp;rendert standardmäßig eine HTML-Liste:</p>



<pre class="wp-block-code"><code>&lt;ul class="ast-nav-menu"&gt;
  &lt;li class="lang-item lang-item-de current-lang"&gt;&lt;a href="/"&gt;DE&lt;/a&gt;&lt;/li&gt;
  &lt;li class="lang-item lang-item-en"&gt;&lt;a href="/en/"&gt;EN&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</code></pre>



<p>Das resultierende Markup muss je nach Theme per CSS an das Header-Layout angepasst werden – insbesondere Darstellung, Abstände und Hervorhebung der aktiven Sprache.</p>



<p><strong>Vorteile gegenüber Variante B:</strong></p>



<ul class="wp-block-list">
<li>Keine statischen URLs – funktioniert bei Domainwechsel und Staging ohne Anpassung</li>



<li>Artikelgenaue Umschaltung automatisch</li>



<li>Neue Sprachen werden automatisch eingebunden</li>
</ul>



<p><strong>Für produktive Nutzung empfohlen:</strong></p>



<ul class="wp-block-list">
<li>In einem <strong>Child-Theme</strong> umsetzen, damit Theme-Updates den Code nicht überschreiben</li>



<li>CSS für aktive Sprache, Kontrast und Fokus-Stil ergänzen (→ Accessibility, siehe unten)</li>



<li>Nach jedem Theme-Update prüfen, ob Hook-Positionen noch stimmen<br><strong>Hinweis:</strong> <code>pll_the_languages()</code> gibt eine HTML-Liste aus und sollte in einem sichtbaren Frontend-Bereich eingebunden werden – nicht im <code>&lt;head></code> der Seite.</li>
</ul>



<h2 class="wp-block-heading">Go-live-Checkliste</h2>



<p>Bevor du die zweisprachige Website offiziell in Betrieb nimmst, diese Punkte abhaken.<br><strong>🔴 Pflicht</strong>&nbsp;·&nbsp;<strong>🟡 Optional</strong>&nbsp;·&nbsp;<strong>🔵 Nur Variante B</strong>&nbsp;·&nbsp;<strong>🟢 Nur bei aktivem Redirect</strong></p>



<p><strong>Grundfunktion:</strong></p>



<ul class="wp-block-list">
<li>🔴 DE-Startseite lädt korrekt (<code>deine-domain.de/</code>)</li>



<li>🔴 EN-Startseite lädt korrekt (<code>deine-domain.de/en/</code>) – kein 404</li>



<li>🔴 Permalinks wurden neu gespeichert</li>



<li>🔴 Cache nach allen Änderungen geleert</li>
</ul>



<p><strong>Navigation:</strong></p>



<ul class="wp-block-list">
<li>🔴 Deutsches Menü zeigt korrekte Kategorien</li>



<li>🔴 Englisches Menü zeigt korrekte Kategorien</li>



<li>🔴 Sprachumschalter sichtbar</li>



<li>🔴 Aktive Sprache wird fett und farbig hervorgehoben</li>
</ul>



<p><strong>Sprachumschaltung:</strong></p>



<ul class="wp-block-list">
<li>🔴 <strong>Variante A / C:</strong> Klick auf EN von DE-Artikel → landet direkt auf englischer Übersetzung</li>



<li>🔴 <strong>Variante A / C:</strong> Klick auf DE von EN-Artikel → landet direkt auf deutschem Original</li>



<li>🔵 <strong>Variante B:</strong> Header-Switcher zeigt korrekt auf <code>/</code> (DE) und <code>/en/</code> (EN)</li>



<li>🔵 <strong>Variante B:</strong> Verhalten auf Unterseiten bewusst getestet und dokumentiert</li>
</ul>



<p><strong>Inhalte:</strong></p>



<ul class="wp-block-list">
<li>🔴 Mindestens ein DE/EN-Beitrag testweise übersetzt und verknüpft</li>



<li>🔴 Rechtliche Seiten in beiden Sprachen vorhanden</li>
</ul>



<p><strong>Browser-Redirect:</strong></p>



<ul class="wp-block-list">
<li>🟢 Browser-Redirect in Inkognito-Tab getestet (kein Admin-Cookie)</li>



<li>🟢 Google Search Console: keine neuen Crawling-Fehler nach Aktivierung</li>
</ul>



<p><strong>Technik:</strong></p>



<ul class="wp-block-list">
<li>🔴 Desktop, Tablet und Mobile geprüft</li>



<li>🟡 Accessibility: Sprachumschalter per Tastatur erreichbar, ausreichender Kontrast</li>



<li>🟡 XML-Sitemap: EN-URLs erscheinen in der Sitemap (SEO-Plugin ggf. neu generieren)</li>
</ul>



<h2 class="wp-block-heading">Zusammenfassung: Was wurde eingerichtet?</h2>



<p><strong>Gemeinsame Grundlage (alle Varianten):</strong></p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Was</th><th>Ergebnis</th></tr></thead><tbody><tr><td>Plugin</td><td>Polylang (kostenlos)</td></tr><tr><td>Sprachen</td><td>Deutsch (de_DE) + Englisch (en_US)</td></tr><tr><td>URL-Struktur</td><td>DE:&nbsp;<code>deine-domain.de/</code>&nbsp;· EN:&nbsp;<code>deine-domain.de/en/</code></td></tr><tr><td>Bestehende Inhalte</td><td>Alle als „Deutsch&#8220; markiert</td></tr><tr><td>Englisches Menü</td><td>Separate Navigation mit übersetzten Kategorienamen</td></tr></tbody></table></figure>



<p><strong>Variante A – Standard:</strong></p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Was</th><th>Ergebnis</th></tr></thead><tbody><tr><td>Sprachumschalter</td><td>Nativer Polylang-Switcher im Menü, dynamisch, artikelgenau</td></tr><tr><td>Wartungsaufwand</td><td>Gering</td></tr></tbody></table></figure>



<p><strong>Variante B – Astra Free zentriert (dieser Guide):</strong></p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Was</th><th>Ergebnis</th></tr></thead><tbody><tr><td>Sprachumschalter</td><td>Statisches HTML-Widget, zentriert im Header</td></tr><tr><td>Styling</td><td>Aktive Sprache fett + Akzentfarbe per&nbsp;<code>html[lang]</code>-Selektor</td></tr><tr><td>Artikelgenaue Umschaltung</td><td>Nur mit zusätzlichem nativen Polylang-Switcher</td></tr><tr><td>Wartungsaufwand</td><td>Mittel – URLs bei Domainwechsel manuell anpassen</td></tr></tbody></table></figure>



<p><strong>Optional (unabhängig von Variante):</strong></p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Was</th><th>Ergebnis</th></tr></thead><tbody><tr><td>Browsersprache-Erkennung</td><td>Automatische Weiterleitung für neue Besucher</td></tr><tr><td>EN-Fallback</td><td>Alle Nicht-DE-Sprachen → Englisch (Produktentscheidung)</td></tr><tr><td>Cache-Ausnahme</td><td>Startseite vom Cache ausgeschlossen (nur bei aktivem Redirect nötig)</td></tr><tr><td>PHP-Snippets</td><td>Über „Code Snippets&#8220;-Plugin, nicht direkt in functions.php</td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Accessibility-Hinweise</h2>



<p>Beim eigenen HTML-Widget (Variante B) ist Barrierefreiheit nicht automatisch gewährleistet. Das klingt nach Bürokratie – ist aber für Tastaturnutzer und Screenreader-Nutzer ein echter Unterschied. Diese Punkte solltest du prüfen und ergänzen:<br><strong><code>aria-label</code>&nbsp;am Nav-Element:</strong></p>



<pre class="wp-block-code"><code>&lt;nav class="pll-switcher-center" aria-label="Sprache wechseln"&gt;
  &lt;a href="..." class="pll-link-de" hreflang="de" lang="de"&gt;DE&lt;/a&gt;
  &lt;span class="pll-sep" aria-hidden="true"&gt;|&lt;/span&gt;
  &lt;a href="..." class="pll-link-en" hreflang="en" lang="en"&gt;EN&lt;/a&gt;
&lt;/nav&gt;
</code></pre>



<p><strong>Aktive Sprache nicht nur über Farbe kennzeichnen</strong>&nbsp;– ergänze&nbsp;<code>aria-current="true"</code>&nbsp;auf dem aktiven Link oder stelle sicher, dass die Fettung allein als visueller Unterschied ausreicht. Farbe allein ist laut WCAG kein ausreichendes Unterscheidungsmerkmal.<br><strong>Kontrast prüfen:</strong>&nbsp;Die inaktive Farbe (<code>#888</code>&nbsp;im Beispiel-CSS) hat gegen einen weißen Header möglicherweise zu wenig Kontrast. Ziel: mindestens 4,5:1 für normalen Text (WCAG AA).<br><strong>Fokus-Stil:</strong>&nbsp;Stelle sicher, dass die Links per Tastatur erreichbar sind und einen sichtbaren Fokus-Rahmen haben. Viele Themes entfernen den Browser-Standard-Fokus per&nbsp;<code>outline: none</code>. Ergänze im Customizer CSS:</p>



<pre class="wp-block-code"><code>.pll-switcher-center a:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 2px;
}
</code></pre>



<p>Das sorgt für einen sichtbaren Fokusrahmen bei Tastaturnavigation, ohne das visuelle Design bei Mausnutzung zu beeinflussen.</p>



<h2 class="wp-block-heading">SEO-Prüfung nach den ersten Übersetzungen</h2>



<p>Sobald die ersten Beiträge in beiden Sprachen veröffentlicht sind, diese Punkte prüfen:<br><strong>hreflang-Tags:</strong></p>



<ul class="wp-block-list">
<li>Sind die <code>hreflang</code>-Tags paarweise korrekt? DE-Seite verweist auf EN, EN-Seite verweist auf DE.</li>



<li>Im Seitenquelltext prüfen: <code>&lt;link rel="alternate" hreflang="de" href="..."/></code> und <code>&lt;link rel="alternate" hreflang="en" href="..."/></code>müssen beide vorhanden sein.<br><strong>Canonicals:</strong></li>



<li>Zeigt jede Seite auf sich selbst als Canonical? DE-Seite → DE-URL, EN-Seite → EN-URL. Keine Kreuz-Verlinkung.<br><strong>Indexierung:</strong></li>



<li>EN-Seiten indexierbar? In Google Search Console prüfen, ob <code>/en/</code>-URLs gecrawlt und indexiert werden.</li>



<li>Leere EN-Entwürfe (ohne Inhalt) nicht indexieren – entweder auf <code>noindex</code> setzen oder erst veröffentlichen, wenn Inhalt vorhanden.<br><strong>Interne Links:</strong></li>



<li>Sind interne Links innerhalb eines Sprachbereichs konsistent? Deutsche Artikel verlinken auf deutsche Seiten, englische auf englische.<br><strong>XML-Sitemap:</strong></li>



<li>Tauchen EN-URLs in der Sitemap auf? Nach dem Veröffentlichen erster englischer Beiträge das SEO-Plugin (Rank Math, Yoast, o.ä.) öffnen und die Sitemap einmal neu generieren lassen.</li>



<li>In der Google Search Console die Sitemap einreichen und prüfen, ob EN-Seiten ohne Fehler indexiert werden.</li>
</ul>



<h2 class="wp-block-heading">Nächste Schritte</h2>



<p>Die technische Einrichtung ist vollständig. Tanja nickt zufrieden. Ulf schaut aus dem Fenster. Bernd öffnet gerade ein neues Browserfenster – man weiß nie.<br>Jetzt kannst du Schritt für Schritt Inhalte auf Englisch ergänzen:</p>



<ol class="wp-block-list">
<li>Rechtlich relevante Seiten zuerst: Impressum → Legal Notice, Datenschutz → Privacy Policy</li>



<li>Dann die wichtigsten Artikel übersetzen</li>



<li>Jede übersetzte Seite erscheint automatisch im Sprachumschalter des entsprechenden DE-Artikels</li>
</ol>



<p><strong>Ulf:</strong>&nbsp;„Das war gar nicht so schlimm.&#8220;<br><strong>Tanja:</strong>&nbsp;„Das sagen alle am Ende.&#8220;<br><strong>Bernd:</strong>&nbsp;„Ich hätte das in zehn Minuten gemacht.&#8220;<br><strong>Tanja:</strong>&nbsp;„Bernd, du bist immer noch nicht fertig mit deinem Backup von letztem Monat.&#8220;<br><strong>Bernd:</strong>&nbsp;„Das ist ein laufendes Projekt.&#8220;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.foundic.org/de/wordpress-zweisprachig-machen-polylang-de-en-anleitung/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>OpenClaw auf Synology DiskStation DS1621+ installieren &#8211; Schritt-für-Schritt Anleitung</title>
		<link>https://www.foundic.org/de/openclaw-synology-diskstation-installieren/</link>
					<comments>https://www.foundic.org/de/openclaw-synology-diskstation-installieren/#respond</comments>
		
		<dc:creator><![CDATA[Michael Müller]]></dc:creator>
		<pubDate>Sun, 29 Mar 2026 18:39:00 +0000</pubDate>
				<category><![CDATA[Projekte]]></category>
		<guid isPermaLink="false">https://www.foundic.org/?p=1034</guid>

					<description><![CDATA[Was ist OpenClaw – und was wirst du am Ende haben? OpenClaw ist ein KI-Agent, den du lokal auf deiner Synology DiskStation betreibst. Statt in der Cloud läuft er bei dir zu Hause – du behältst die Kontrolle über deine Daten, zahlst nur für die tatsächlich genutzten API-Anfragen und erreichst deinen persönlichen Assistenten per Telegram [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h3 class="wp-block-heading">Was ist OpenClaw – und was wirst du am Ende haben?</h3>



<p>OpenClaw ist ein KI-Agent, den du lokal auf deiner Synology DiskStation betreibst. Statt in der Cloud läuft er bei dir zu Hause – du behältst die Kontrolle über deine Daten, zahlst nur für die tatsächlich genutzten API-Anfragen und erreichst deinen persönlichen Assistenten per Telegram oder Browser.</p>



<p>Am Ende dieser Anleitung hast du:</p>



<ul class="wp-block-list">
<li>Einen laufenden OpenClaw-Container auf deiner DiskStation</li>



<li>Einen Telegram-Bot, dem du auf deinem Smartphone einfach schreiben kannst</li>



<li>Eine optionale Web-Oberfläche, erreichbar per SSH-Tunnel im Browser</li>



<li>Optional: Netzwerk-Isolation, die dem Container den Zugriff auf dein Heimnetz verwehrt</li>



<li>Optional: Einen eingebetteten Browser, mit dem OpenClaw auch JavaScript-lastige Webseiten bedienen kann</li>
</ul>



<p>Die Grundinstallation – Container läuft, Telegram antwortet – dauert etwa 30 Minuten. Die optionalen Schritte kommen danach, wenn das Fundament steht.</p>



<h3 class="wp-block-heading">Voraussetzungen</h3>



<p>Bevor du anfängst – stelle sicher, dass du das Folgende zur Hand hast:</p>



<ul class="wp-block-list">
<li>Synology DS1621+ mit aktuellem DSM 7.2 oder neuer</li>



<li>Container Manager installiert (aus dem Paket-Zentrum)</li>



<li>SSH-Zugang zur DiskStation (wird in dieser Anleitung erklärt)</li>



<li>Einen API-Schlüssel von Anthropic (Claude) oder OpenAI</li>



<li>Telegram auf dem Smartphone</li>
</ul>



<p><strong>Noch kein API-Key?</strong>&nbsp;Für Claude gehe auf&nbsp;<a href="https://console.anthropic.com/" target="_blank" rel="noreferrer noopener">console.anthropic.com</a>, melde dich an, hinterlege eine Zahlungsmethode und erstelle einen Schlüssel. Er beginnt mit&nbsp;<code>sk-ant-...</code></p>



<h3 class="wp-block-heading">Architektur auf einen Blick</h3>



<p>So sieht die fertige Ordnerstruktur auf deiner DiskStation aus. Sie entsteht Schritt für Schritt – du musst nichts manuell vorbereiten.</p>



<pre class="wp-block-code"><code>/volume1/docker/openclaw/
├── compose.yaml             ← Container-Konfiguration (Berechtigungen, Netzwerk, Volumes)
├── openclaw-firewall.sh     ← Netzwerk-Isolation (optional, aber empfohlen)
├── config/                  ← API-Keys, Einstellungen (wird beim Onboarding befüllt)
└── workspace/               ← Arbeitsdateien des Agenten</code></pre>



<p>OpenClaw besteht aus zwei Diensten, die in der&nbsp;<code>compose.yaml</code>&nbsp;definiert sind:</p>



<ul class="wp-block-list">
<li><strong>openclaw-gateway</strong>&nbsp;– der dauerhaft laufende Dienst. Er hält die Verbindung zu Telegram, stellt die Web-UI bereit und kommuniziert mit der KI-API.</li>



<li><strong>openclaw-cli</strong>&nbsp;– ein Einmal-Container für Verwaltungsaufgaben (Onboarding, Konfiguration, Pairing). Er startet auf Abruf und beendet sich danach selbst.</li>
</ul>



<h2 class="wp-block-heading">Container oder VM? Die erste große Entscheidung</h2>



<p><strong>Um diese Anleitung verständlicher zu machen, begleiten dich drei Personen:</strong><br>Die typischen Büro-Charaktere: Die kompetente IT-Kollegin, der selbsternannte Experte und der ehrliche Anfänger. Diese drei Perspektiven helfen dir, typische Stolperfallen zu erkennen.<br><strong>Tanja</strong>&nbsp;ist die IT-Expertin. Sie weiß, wie es funktioniert, erklärt geduldig und strukturiert – und lässt sich von schlechten Ratschlägen nicht aus der Ruhe bringen. Wenn du eine Frage hast, hat Tanja die Antwort.<br><strong>Bernd</strong>&nbsp;ist der selbsternannte „Experte“, der alles besser weiß – und meistens falsch liegt. Seine Abkürzungen und sein Halbwissen führen regelmäßig zu Problemen. Er steht für alle gefährlichen Mythen und schlechten Praktiken, die du vermeiden solltest.<br><strong>Ulf</strong>&nbsp;ist der Lernende, genau wie du. Er stellt die Fragen, die dir im Kopf herumschwirren, und braucht manchmal einen Vergleich aus dem Alltag, um IT zu verstehen. Wenn Ulf etwas nicht versteht, ist das völlig in Ordnung, dafür ist Tanja da.&nbsp;</p>



<p><strong>&#8222;Und… Action!&#8220;</strong></p>



<p>Es ist Montagmorgen. Bernd steht vor dem Whiteboard, Marker in der Hand, und hat „VM&#8220; in Großbuchstaben hingeschrieben. Er lehnt sich zurück, faltet die Arme, sieht sehr zufrieden aus.<br><strong>Bernd:</strong>&nbsp;„VM. Immer VM. Sicherer. Professioneller. Echte Admins nehmen VMs. Ende der Diskussion.&#8220;<br><strong>Ulf:</strong>&nbsp;„Was ist nochmal der Unterschied? VM klingt nach VfL Mönchengladbach.&#8220;<br><strong>Tanja:</strong>&nbsp;„Stell dir eine VM vor wie ein komplett eingerichtetes Fußballstadion – eigene Umkleide, eigener Rasen, eigene Kantine. Ein Docker-Container dagegen ist nur der Spieler mit seinen Fußballschuhen. Kein eigenes Stadion, aber er läuft deutlich schneller auf den Platz.&#8220;<br><strong>Bernd:</strong>&nbsp;„Eben! Deshalb VM – wegen der Isolation!&#8220;<br><strong>Tanja:</strong>&nbsp;„Das stimmt halb, Bernd. Eine VM bietet bessere Kernel-Isolation. Aber OpenClaw wurde als Docker-Applikation gebaut – mit fertigem Dockerfile und docker-compose.yml im Repo. Den Container-Weg wählen wir hier. Und wer wirklich maximale Isolation will, kann OpenClaw auch innerhalb einer VM per Docker Compose installieren – der Rest der Anleitung bleibt dann identisch.&#8220;</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Kriterium</th><th>Container (Docker)</th><th>VM (Synology VMM)</th></tr></thead><tbody><tr><td><strong>Performance</strong></td><td>Besser – kein komplett eigener OS-Kernel nötig</td><td>Schlechter – braucht ca. 2 GB RAM Minimum</td></tr><tr><td><strong>Installation</strong></td><td>Einfach – docker-compose.yml liegt fertig vor</td><td>Aufwändig – OS installieren, Node ≥22 einrichten, Autostart konfigurieren</td></tr><tr><td><strong>Isolation</strong></td><td>Prozess-Isolation auf Kernel-Ebene</td><td>Vollständige Kernel-Isolation, kein direkter Host-Zugriff</td></tr><tr><td><strong>Zusammenfassung</strong></td><td>Performanter, leichter, näher an der offiziellen OpenClaw-Installation</td><td>Stärkere Isolation, aber schwerer und ressourcenintensiver</td></tr></tbody></table></figure>



<p>Diese Anleitung geht den Container-Weg. Die zusätzlichen iptables-Regeln im optionalen Sicherheitskapitel reduzieren das Risiko, dass ein kompromittierter Container interne Geräte im Heimnetz erreicht. Sie ersetzen jedoch keine VM-Isolation, kein Patch-Management und keine sorgfältige Prüfung der eingesetzten Container-Images.</p>



<h2 class="wp-block-heading">Teil 1: Vorbereitung auf der DiskStation</h2>



<h3 class="wp-block-heading">Schritt 1.1: Container Manager installieren</h3>



<p><strong>Ulf:</strong>&nbsp;„Container Manager – ist das so eine Art Transfer-Manager für Docker-Spieler?&#8220;<br><strong>Tanja:</strong>&nbsp;„Fast! Container Manager ist die grafische Oberfläche auf deiner DiskStation, über die du Docker-Container startest, stoppst und überwachst. Ohne ihn läuft gar nichts.&#8220;<br><strong>Bernd:</strong>&nbsp;„Hab ich nie gebraucht. Ich mach das alles per SSH. Echter Admin braucht keine GUI.&#8220;<br><strong>Tanja:</strong>&nbsp;„Bernd, du hast letzten Monat versehentlich alle Container gelöscht, weil du dich in der IP vertippt hast.&#8220;</p>



<ol class="wp-block-list">
<li>Öffne die DiskStation-Oberfläche im Browser.</li>



<li>Öffne das&nbsp;<strong>Paket-Zentrum</strong>.</li>



<li>Suche nach&nbsp;<strong>Container Manager</strong>.</li>



<li>Klicke&nbsp;<strong>Installieren</strong>&nbsp;– falls nicht bereits vorhanden.</li>
</ol>



<h3 class="wp-block-heading">Schritt 1.2: SSH aktivieren</h3>



<p>SSH (Secure Shell) ist dein verschlüsselter Tunnel direkt in die DiskStation. Statt für jeden Befehl durch die Weboberfläche zu klicken, kannst du Befehle direkt eintippen – wie eine Direktverbindung zum Herzstück deines Servers.</p>



<p><strong>Bernd:</strong>&nbsp;„Ich hab SSH dauerhaft offen und Port 22 direkt ins Internet weitergeleitet. Effizienter.&#8220;<br><strong>Tanja:</strong>&nbsp;„&#8230; Das machen wir nicht. SSH ist hier nur für die Verbindung im lokalen Netzwerk gedacht.&#8220;</p>



<ol class="wp-block-list">
<li>Öffne die&nbsp;<strong>Systemsteuerung</strong>.</li>



<li>Gehe zu&nbsp;<strong>Terminal &amp; SNMP</strong>.</li>



<li>Setze den Haken bei&nbsp;<strong>SSH-Dienst aktivieren</strong>.</li>



<li>Port bleibt auf&nbsp;<strong>22</strong>.</li>



<li>Klicke&nbsp;<strong>Übernehmen</strong>.</li>
</ol>



<h3 class="wp-block-heading">Schritt 1.3: Per SSH verbinden</h3>



<p>Jetzt verbindest du dich zum ersten Mal mit deiner DiskStation über das Terminal. Keine Sorge – das ist kein schwarzer Bildschirm aus einem Hacker-Film. Es ist nur ein Textfenster, in dem du Befehle tippst.</p>



<p><strong>Auf dem Mac</strong>&nbsp;(Programme → Dienstprogramme → Terminal):</p>



<pre class="wp-block-code"><code>ssh dein-benutzername@deine_NAS_IP
</code></pre>



<p><strong>Auf Windows</strong>&nbsp;(Windows-Taste,&nbsp;<code>cmd</code>, Enter):</p>



<pre class="wp-block-code"><code>ssh dein-benutzername@deine_NAS_IP
</code></pre>



<p>Die IP-Adresse deiner DiskStation findest du in DSM unter Systemsteuerung → Netzwerk → Netzwerkschnittstelle.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440082dfb7&quot;}" data-wp-interactive="core/image" data-wp-key="69e440082dfb7" class="wp-block-image aligncenter size-full wp-lightbox-container"><img loading="lazy" decoding="async" width="594" height="377" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/03/Bild-1-mit-Terminal-auf-Diskstation-einloggen.png" alt="Bild 1 - Mit Terminal auf DiskStation einloggen" class="wp-image-1035" srcset="https://www.foundic.org/wp-content/uploads/2026/03/Bild-1-mit-Terminal-auf-Diskstation-einloggen.png 594w, https://www.foundic.org/wp-content/uploads/2026/03/Bild-1-mit-Terminal-auf-Diskstation-einloggen-300x190.png 300w" sizes="auto, (max-width: 594px) 100vw, 594px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 1 &#8211; Mit Terminal auf DiskStation einloggen</figcaption></figure>



<h3 class="wp-block-heading">Schritt 1.4: Ordner anlegen</h3>



<p>Nach dem ersten Login wechselst du zu root. Ohne root-Rechte darfst du keine Ordner in&nbsp;<code>/volume1/</code>&nbsp;anlegen.</p>



<p><strong>Ulf:</strong>&nbsp;„Root, ist das der Kapitän des Systems?&#8220;<br><strong>Tanja:</strong>&nbsp;„Root ist der Admin aller Admins. Auf einem Linux-System darf root alles. Wir brauchen root jetzt für die Ordner – danach läuft der Container aber bewusst nicht als root.&#8220;</p>



<p>Nachdem du per SSH verbunden bist:</p>



<pre class="wp-block-code"><code># Zu root wechseln
sudo -i

# Ordner erstellen
mkdir -p /volume1/docker/openclaw/config
mkdir -p /volume1/docker/openclaw/workspace

# Rechte setzen
chown -R 1000:1000 /volume1/docker/openclaw
chmod -R 755 /volume1/docker/openclaw
</code></pre>



<p>&nbsp;<strong>Warum 1000:1000?</strong>&nbsp;Das ist die User-ID, unter der der Container später läuft. Indem du die Ordner schon jetzt auf diesen Nutzer setzt, hat der Container die nötigen Schreibrechte – ohne Administratorrechte zu benötigen.</p>



<h4 class="wp-block-heading">Soll-Ergebnis – so prüfst du, ob es geklappt hat:</h4>



<pre class="wp-block-code"><code>ls -la /volume1/docker/openclaw/
</code></pre>



<p>Du solltest sehen, dass beide Unterordner (<code>config</code>,&nbsp;<code>workspace</code>) dem Benutzer mit UID 1000 gehören:</p>



<pre class="wp-block-code"><code>drwxr-xr-x  1000 users  config/
drwxr-xr-x  1000 users  workspace/
</code></pre>



<h3 class="wp-block-heading">Schritt 1.5: compose.yaml erstellen</h3>



<p>Jetzt wird es konkret. Die&nbsp;<code>compose.yaml</code>&nbsp;ist das Herzstück: Hier steht alles drin, was der Container braucht – Berechtigungen, Netzwerk, Volumes, Sicherheitseinstellungen.</p>



<p><strong>Ulf:</strong>&nbsp;„Compose.yaml – ist das wie der Aufstellungszettel vor dem Anpfiff?&#8220;<br><strong>Tanja:</strong>&nbsp;„Genau so! Stell dir vor: Der Trainer schreibt auf, wer spielen darf, welche Position er hat, und was verboten ist. Genau das macht die compose.yaml für deinen Container.&#8220;<br><strong>Bernd:</strong>&nbsp;„Ich mach das alles ohne Compose-Datei.&nbsp;<code>docker run</code>&nbsp;mit zehn Flags ist viel flexibler.&#8220;<br><strong>Tanja:</strong>&nbsp;„Und wenn du beim nächsten Neustart die Flags nicht mehr weißt?&#8220;<br><strong>Bernd:</strong>&nbsp;„&#8230;dann fang ich halt neu an.&#8220;</p>



<p>Immer noch in der SSH-Sitzung als root. Kopiere den kompletten Block und füge ihn im Terminal ein:</p>



<pre class="wp-block-code"><code>cat &gt; /volume1/docker/openclaw/compose.yaml &lt;&lt; 'DATEIENDE'
services:
  openclaw-gateway:
    image: ghcr.io/openclaw/openclaw:latest
    container_name: openclaw-gateway
    restart: unless-stopped
    user: "1000:1000"
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    read_only: true
    tmpfs:
      - /tmp
      - /run
    pids_limit: 256
    dns:
      - 1.1.1.1
      - 8.8.8.8
    networks:
      - openclaw-isolated
    ports:
      - "18789:18789"
    volumes:
      - /volume1/docker/openclaw/config:/home/node/.openclaw
      - /volume1/docker/openclaw/workspace:/home/node/.openclaw/workspace
    environment:
      - HOME=/home/node
      - TERM=xterm-256color
      - NODE_ENV=production
    healthcheck:
      test: &#91;"CMD-SHELL", "wget -qO- http://127.0.0.1:18789/ &gt;/dev/null 2&gt;&amp;1 || exit 1"]
      interval: 60s
      timeout: 10s
      retries: 3
      start_period: 30s
    init: true
    command:
      &#91;
        "node",
        "dist/index.js",
        "gateway",
        "--bind",
        "lan",
        "--port",
        "18789",
      ]

  openclaw-cli:
    image: ghcr.io/openclaw/openclaw:latest
    container_name: openclaw-cli
    user: "1000:1000"
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    network_mode: "service:openclaw-gateway"
    volumes:
      - /volume1/docker/openclaw/config:/home/node/.openclaw
      - /volume1/docker/openclaw/workspace:/home/node/.openclaw/workspace
    environment:
      - HOME=/home/node
      - TERM=xterm-256color
      - NODE_ENV=production
    stdin_open: true
    tty: true
    init: true
    entrypoint: &#91;"node", "dist/index.js"]
    profiles:
      - cli

networks:
  openclaw-isolated:
    driver: bridge
    ipam:
      config:
        - subnet: 172.30.0.0/24
          gateway: 172.30.0.1
DATEIENDE</code></pre>



<p><strong>Was bedeuten die wichtigsten Einstellungen?</strong></p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Einstellung</th><th>Bedeutung</th></tr></thead><tbody><tr><td><code>user: "1000:1000"</code></td><td>Container läuft nicht als root – kein Administratorzugriff.</td></tr><tr><td><code>cap_drop: ALL</code></td><td>Alle Linux-Sonderrechte (Capabilities) werden entzogen.</td></tr><tr><td><code>read_only: true</code></td><td>Root-Dateisystem schreibgeschützt – Schadsoftware kann sich nicht dauerhaft festsetzen.</td></tr><tr><td><code>tmpfs: /tmp, /run</code></td><td>Temporärer Speicher im Arbeitsspeicher für Programme, die dort schreiben müssen.</td></tr><tr><td><code>pids_limit: 256</code></td><td>Maximal 256 Prozesse – Schutz gegen Fork-Bombs.</td></tr><tr><td><code>dns: 1.1.1.1 / 8.8.8.8</code></td><td>DNS-Anfragen gehen direkt ins Internet. Ohne diese Einstellung würden sie zum Router laufen – der wird durch die optionale Firewall blockiert und der Container hätte kein Internet.</td></tr><tr><td><code>"18789:18789"</code></td><td>Web-UI erreichbar auf Port 18789.</td></tr><tr><td>Kein&nbsp;<code>docker.sock</code>Volume</td><td>Container kann Docker und Host nicht steuern.</td></tr><tr><td><code>subnet: 172.30.0.0/24</code></td><td>Festes Subnetz, das im optionalen Firewall-Kapitel gezielt geblockt werden kann.</td></tr></tbody></table></figure>



<p><strong>Soll-Ergebnis – Datei validieren:</strong></p>



<pre class="wp-block-code"><code>docker compose -f /volume1/docker/openclaw/compose.yaml config</code></pre>



<p><code>docker compose config</code>&nbsp;validiert die Datei und gibt sie normalisiert aus. Das ist verlässlicher als ein reines&nbsp;<code>cat</code>. Du solltest eine vollständige, fehlerfreie YAML-Ausgabe sehen. Eine Fehlermeldung wie&nbsp;<code>mapping values are not allowed here</code>&nbsp;weist auf Einrückungsfehler hin – dann den&nbsp;<code>cat</code>-Block aus dem vorigen Schritt nochmals einfügen.</p>



<h3 class="wp-block-heading">Schritt 1.6: OpenClaw Onboarding durchführen</h3>



<p>Das Onboarding ist ein interaktiver Einrichtungsassistent. Er fragt dich nach API-Key, Modell und Kommunikationskanal – und schreibt danach eine fertige Konfigurationsdatei ins&nbsp;<code>config/</code>-Verzeichnis. Dieser Schritt muss per SSH erledigt werden, weil der Assistent eine direkte Terminalverbindung braucht.</p>



<p><strong>Bernd:</strong>&nbsp;„Ich hab einfach das Image gezogen und gestartet. Lief sofort.&#8220;<br><strong>Tanja:</strong>&nbsp;„Und dann?&#8220;<br><strong>Bernd:</strong>&nbsp;„Dann kam eine Fehlermeldung. Aber das ist normal.&#8220;<br><strong>Tanja:</strong>&nbsp;„Das ist nicht normal. Das ist fehlende Konfiguration. Deshalb machen wir das Onboarding vor dem ersten Start.&#8220;</p>



<pre class="wp-block-code"><code>cd /volume1/docker/openclaw
docker compose run --rm openclaw-cli onboard</code></pre>



<p>Der Assistent führt dich durch folgende Schritte:</p>



<h4 class="wp-block-heading">Schritt 1 – Sicherheitshinweise bestätigen</h4>



<p>Eingabe:&nbsp;<code>Yes</code></p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440082e939&quot;}" data-wp-interactive="core/image" data-wp-key="69e440082e939" class="wp-block-image aligncenter size-full wp-lightbox-container"><img loading="lazy" decoding="async" width="705" height="933" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/03/Bild-2-OpenClaw-Onboarding-Security.png" alt="Bild 2 - OpenClaw - Onboarding - Security" class="wp-image-1037" srcset="https://www.foundic.org/wp-content/uploads/2026/03/Bild-2-OpenClaw-Onboarding-Security.png 705w, https://www.foundic.org/wp-content/uploads/2026/03/Bild-2-OpenClaw-Onboarding-Security-227x300.png 227w" sizes="auto, (max-width: 705px) 100vw, 705px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 2 &#8211; OpenClaw &#8211; Onboarding &#8211; Security</figcaption></figure>



<h4 class="wp-block-heading">Schritt 2 – Onboarding-Modus wählen</h4>



<p>Eingabe:&nbsp;<code>QuickStart</code><br>QuickStart ist der geführte Einrichtungspfad für neue Installationen. Er fragt nur das Nötigste ab und überspringt erweiterte Konfigurationsoptionen.</p>



<h4 class="wp-block-heading">Schritt 3 – KI-Anbieter und Modell wählen</h4>



<p><strong>Ulf:</strong>&nbsp;„Welchen Provider soll ich nehmen? Ist das wie die Wahl zwischen Bundesliga und Champions League?&#8220;<br><strong>Tanja:</strong>&nbsp;„Die Wahl beeinflusst Qualität und Kosten. Hier ein Überblick:&#8220;</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Modell</th><th>Input (pro Mio. Token)</th><th>Output (pro Mio. Token)</th></tr></thead><tbody><tr><td>OpenAI GPT-4.1 nano</td><td>~$0.10</td><td>~$0.40</td></tr><tr><td>OpenAI GPT-4.1 mini</td><td>~$0.40</td><td>~$1.60</td></tr><tr><td>Anthropic Haiku 3.5</td><td>~$0.80</td><td>~$4.00</td></tr><tr><td>OpenAI GPT-4o</td><td>~$2.50</td><td>~$10</td></tr><tr><td>Anthropic Sonnet 4</td><td>~$3.00</td><td>~$15</td></tr></tbody></table></figure>



<p>(Stand Februar 2026)</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440082f001&quot;}" data-wp-interactive="core/image" data-wp-key="69e440082f001" class="wp-block-image aligncenter size-full wp-lightbox-container"><img loading="lazy" decoding="async" width="706" height="941" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/03/Bild-3-OpenClaw-Onboarding-Modelauth-provider.png" alt="Bild 3 - OpenClaw - Onboarding - Model/auth provider" class="wp-image-1039" srcset="https://www.foundic.org/wp-content/uploads/2026/03/Bild-3-OpenClaw-Onboarding-Modelauth-provider.png 706w, https://www.foundic.org/wp-content/uploads/2026/03/Bild-3-OpenClaw-Onboarding-Modelauth-provider-225x300.png 225w" sizes="auto, (max-width: 706px) 100vw, 706px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 3 &#8211; OpenClaw &#8211; Onboarding &#8211; Model/auth provider</figcaption></figure>



<p>Für einen Chat-Assistenten im Heimgebrauch reden wir bei beiden Anbietern eher über Cent-Beträge pro Gespräch. Der Unterschied ist in der Praxis gering.</p>



<p><strong>Empfehlung:</strong>&nbsp;Nimm Anthropic, weil Claude bei längeren Gesprächen und komplexen Anweisungen qualitativ oft stärker ist. Wähle Haiku wenn du sparen möchtest, Sonnet wenn du Qualität willst. Du kannst das jederzeit wechseln. Falls dir vor allem der günstigste Preis wichtig ist: OpenAI mit GPT-4.1 mini oder nano.</p>



<p>Falls du noch keinen API-Key hast: Für Claude gehe auf&nbsp;<a href="https://console.anthropic.com/" target="_blank" rel="noreferrer noopener">console.anthropic.com</a>. Falls du das gerade nicht einrichten willst: Wähle&nbsp;<strong>Back</strong>, dann&nbsp;<strong>Skip for now</strong>. Du kannst den Provider später nachrüsten:</p>



<pre class="wp-block-code"><code>cd /volume1/docker/openclaw
docker compose run --rm openclaw-cli configure</code></pre>



<h4 class="wp-block-heading">Schritt 4 – Authentifizierungsmethode</h4>



<p>Eingabe:&nbsp;<code>Anthropic API key</code></p>



<h4 class="wp-block-heading">Schritt 5 – API-Key eingeben</h4>



<p>Deinen&nbsp;<code>sk-ant-...</code>-Schlüssel eingeben.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440082f6fe&quot;}" data-wp-interactive="core/image" data-wp-key="69e440082f6fe" class="wp-block-image aligncenter size-full wp-lightbox-container"><img loading="lazy" decoding="async" width="708" height="935" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/03/Bild-4-OpenClaw-Onboarding-Enter-Anthropic-API-key.png" alt="Bild 4 - OpenClaw - Onboarding - Enter Anthropic API key" class="wp-image-1040" srcset="https://www.foundic.org/wp-content/uploads/2026/03/Bild-4-OpenClaw-Onboarding-Enter-Anthropic-API-key.png 708w, https://www.foundic.org/wp-content/uploads/2026/03/Bild-4-OpenClaw-Onboarding-Enter-Anthropic-API-key-227x300.png 227w" sizes="auto, (max-width: 708px) 100vw, 708px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 4 &#8211; OpenClaw &#8211; Onboarding &#8211; Enter Anthropic API key</figcaption></figure>



<h4 class="wp-block-heading">Schritt 6 – Standardmodell bestätigen</h4>



<p>Eingabe:&nbsp;<code>Keep current (claude-sonnet-4-6)</code></p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Modell</th><th>Stärke</th><th>Relative Kosten</th></tr></thead><tbody><tr><td>Haiku</td><td>Schnell, günstig – für einfache Aufgaben</td><td>~1/4 von Sonnet</td></tr><tr><td><strong>Sonnet</strong></td><td>Bestes Preis-Leistungs-Verhältnis</td><td>Mittel</td></tr><tr><td>Opus</td><td>Am leistungsfähigsten – für komplexe Aufgaben</td><td>~5× Sonnet</td></tr></tbody></table></figure>



<h4 class="wp-block-heading">Schritt 7 – Kommunikationskanal wählen</h4>



<p>Eingabe:&nbsp;<code>Telegram (Bot API)</code><br>Telegram ist der empfohlene Kanal für die Smartphone-Nutzung. Du hast auch Synology Chat als Option. Falls du dir unsicher bist: Wähle&nbsp;<strong>Skip for now</strong>&nbsp;– Kanäle lassen sich jederzeit nachrüsten.</p>



<h4 class="wp-block-heading">Schritt 8 – Telegram Bot einrichten</h4>



<p>Falls du Telegram gewählt hast, brauchst du einen Bot-Token:</p>



<ol class="wp-block-list">
<li>Öffne Telegram und suche den Kontakt&nbsp;<strong>@BotFather</strong>.</li>



<li>Schreibe ihm:&nbsp;<code>/newbot</code></li>



<li>Vergib einen&nbsp;<strong>Anzeigenamen</strong>&nbsp;(frei wählbar, z.B. „MeinOpenClaw&#8220;) und einen&nbsp;<strong>Benutzernamen</strong>&nbsp;(muss einmalig auf Telegram sein, muss auf&nbsp;<code>bot</code>&nbsp;enden, z.B.&nbsp;<code>meinopenclaw_bot</code>).</li>



<li>BotFather gibt dir einen&nbsp;<strong>Bot-Token</strong>&nbsp;– eine lange Zeichenkette. Den gibst du jetzt im Onboarding-Assistenten ein.</li>
</ol>



<h4 class="wp-block-heading">Schritt 9 – Skills konfigurieren</h4>



<p>Eingabe:&nbsp;<code>No</code><br>Skills sind optionale Zusatzmodule (Browser-Automation, Kalender, Notizen etc.). Sie laden jeweils eigene Software nach und können bei unserem schreibgeschützten Container Konflikte verursachen. Die Kernfunktion – per Telegram mit Claude chatten – funktioniert ohne Skills. Einzelne Skills lassen sich später gezielt nachrüsten.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440082febe&quot;}" data-wp-interactive="core/image" data-wp-key="69e440082febe" class="wp-block-image aligncenter size-full wp-lightbox-container"><img loading="lazy" decoding="async" width="708" height="933" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/03/Bild-5-OpenClaw-Onboarding-Install-missing-skill-dependencies.png" alt="Bild 5 - OpenClaw - Onboarding - Install missing skill dependencies" class="wp-image-1042" srcset="https://www.foundic.org/wp-content/uploads/2026/03/Bild-5-OpenClaw-Onboarding-Install-missing-skill-dependencies.png 708w, https://www.foundic.org/wp-content/uploads/2026/03/Bild-5-OpenClaw-Onboarding-Install-missing-skill-dependencies-228x300.png 228w" sizes="auto, (max-width: 708px) 100vw, 708px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 5 &#8211; OpenClaw &#8211; Onboarding &#8211; Install missing skill dependencies</figcaption></figure>



<h4 class="wp-block-heading">Schritte 10 &#8211; 15 Weitere API-Keys (Google Places, Gemini, Notion, OpenAI-Image, Whisper, ElevenLabs)</h4>



<p>Alle mit&nbsp;<code>No</code>&nbsp;beantworten. Das sind optionale Skills für spezielle Anwendungsfälle.</p>



<h4 class="wp-block-heading">Schritt 16 – Hooks aktivieren</h4>



<p>Eingabe:&nbsp;<code>Skip for now</code><br>Hooks sind Automatisierungen, die bei bestimmten Ereignissen ausgelöst werden. Für den Start nicht nötig.</p>



<h4 class="wp-block-heading">Das Onboarding ist abgeschlossen!</h4>



<p>&nbsp;<strong>Wichtig:</strong>&nbsp;Schreibe dir den&nbsp;<strong>Gateway Token</strong>&nbsp;auf, der am Ende des Onboardings angezeigt wird. Er sieht so aus:</p>



<pre class="wp-block-code"><code>#token=2bbea678f.........................67003d38</code></pre>



<p>Du brauchst ihn für die optionale Web-Oberfläche. Schreib ihn jetzt auf.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440083059d&quot;}" data-wp-interactive="core/image" data-wp-key="69e440083059d" class="wp-block-image aligncenter size-full wp-lightbox-container"><img loading="lazy" decoding="async" width="797" height="933" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/03/Bild-6-OpenClaw-Onboarding-Complete.png" alt="Bild 6 - OpenClaw - Onboarding - Complete" class="wp-image-1043" srcset="https://www.foundic.org/wp-content/uploads/2026/03/Bild-6-OpenClaw-Onboarding-Complete.png 797w, https://www.foundic.org/wp-content/uploads/2026/03/Bild-6-OpenClaw-Onboarding-Complete-256x300.png 256w, https://www.foundic.org/wp-content/uploads/2026/03/Bild-6-OpenClaw-Onboarding-Complete-768x899.png 768w" sizes="auto, (max-width: 797px) 100vw, 797px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 6 &#8211; OpenClaw &#8211; Onboarding &#8211; Complete</figcaption></figure>



<p>Bevor du den Gateway zum ersten Mal startest, ein notwendiger Konfigurationsschritt. Ohne ihn startet der Gateway mit einem Fehler:</p>



<pre class="wp-block-code"><code>cd&nbsp;/volume1/docker/openclaw
docker compose run --rm openclaw-cli config set gateway.controlUi.allowedOrigins '&#91;"http://localhost:18789"]'</code></pre>



<p><strong>Was ist&nbsp;<code>allowedOrigins</code>?</strong>&nbsp;Das ist eine Sicherheitseinstellung, die festlegt, von welchen Adressen aus die Control UI – die Web-Oberfläche des Gateways – aufgerufen werden darf. Ohne diese Freigabe verweigert OpenClaw den Zugriff, weil die Web-UI über&nbsp;<code>localhost</code>&nbsp;(per SSH-Tunnel) erreichbar ist, was standardmäßig nicht erlaubt ist.</p>



<h3 class="wp-block-heading">Schritt 1.7: Container starten</h3>



<h4 class="wp-block-heading">Variante A: Über Container Manager</h4>



<ol class="wp-block-list">
<li>Öffne&nbsp;<strong>Container Manager</strong>&nbsp;in der DiskStation-Oberfläche.</li>



<li>Gehe zu&nbsp;<strong>Projekt</strong>.</li>



<li>Klicke&nbsp;<strong>Erstellen</strong>.</li>



<li><strong>Projektname:</strong>&nbsp;<code>openclaw</code></li>



<li><strong>Pfad:</strong>&nbsp;<code>/volume1/docker/openclaw</code></li>



<li>Container Manager zeigt die compose.yaml an →&nbsp;<strong>Weiter</strong>&nbsp;→&nbsp;<strong>Erstellen</strong>.</li>
</ol>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400830d6b&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400830d6b" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="751" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/03/Bild-7-Container-Manager-Projekt-erstellen-Allgemeine-Einstellungen-1024x751.png" alt="Bild 7 - Container Manager - Projekt erstellen - Allgemeine Einstellungen" class="wp-image-1044" srcset="https://www.foundic.org/wp-content/uploads/2026/03/Bild-7-Container-Manager-Projekt-erstellen-Allgemeine-Einstellungen-1024x751.png 1024w, https://www.foundic.org/wp-content/uploads/2026/03/Bild-7-Container-Manager-Projekt-erstellen-Allgemeine-Einstellungen-300x220.png 300w, https://www.foundic.org/wp-content/uploads/2026/03/Bild-7-Container-Manager-Projekt-erstellen-Allgemeine-Einstellungen-768x563.png 768w, https://www.foundic.org/wp-content/uploads/2026/03/Bild-7-Container-Manager-Projekt-erstellen-Allgemeine-Einstellungen.png 1220w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 7 &#8211; Container Manager &#8211; Projekt erstellen &#8211; Allgemeine Einstellungen</figcaption></figure>



<p>Der erste Download des Images dauert erfahrungsgemäß rund 8 Minuten. Wenn du Container Manager verwendest und das Projekt vor dem Onboarding erstellt hast: Container Manager startet das Projekt sofort nach dem Erstellen. Der Container meldet dann „Missing config&#8220; und beendet sich. Das ist kein Fehler – stoppe das Projekt, führe das Onboarding durch (Schritt 1.6), und starte dann neu.</p>



<h4 class="wp-block-heading">Variante B: Per SSH</h4>



<pre class="wp-block-code"><code>cd /volume1/docker/openclaw
docker compose up -d openclaw-gateway</code></pre>



<p><strong>Soll-Ergebnis – so prüfst du, ob der Container läuft:</strong></p>



<pre class="wp-block-code"><code># Läuft der Container?
docker ps --filter name=openclaw-gateway

# Was sagen die Logs?
docker logs openclaw-gateway --tail 50</code></pre>



<p>Was du sehen solltest:</p>



<pre class="wp-block-code"><code>&#91;gateway] listening on ws://0.0.0.0:18789
&#91;telegram] starting provider (@dein_botname)</code></pre>



<p>Was normale Erststart-Meldungen sind (kein Fehler):</p>



<ul class="wp-block-list">
<li><code>[warn] pids_limit discarded</code>&nbsp;– der Synology-Kernel unterstützt dieses Feature nicht, es wird ignoriert.<br>Was ein echter Fehler ist:</li>



<li><code>Missing config</code>&nbsp;→ Onboarding (Schritt 1.6) nicht abgeschlossen.</li>



<li><code>non-loopback Control UI requires allowedOrigins</code>&nbsp;→ den&nbsp;<code>config set</code>-Befehl am Ende von Schritt 1.6 nachholen.</li>



<li><code>Error: EACCES: permission denied</code>&nbsp;→ Ordnerrechte prüfen (<code>chown -R 1000:1000 /volume1/docker/openclaw</code>).</li>
</ul>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400831533&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400831533" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="753" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/03/Bild-8-Container-Manager-Projekt-erstellen-erfolgreich-abgeschlossen-1024x753.png" alt="Bild 8 - Container Manager - Projekt erstellen - erfolgreich abgeschlossen" class="wp-image-1046" srcset="https://www.foundic.org/wp-content/uploads/2026/03/Bild-8-Container-Manager-Projekt-erstellen-erfolgreich-abgeschlossen-1024x753.png 1024w, https://www.foundic.org/wp-content/uploads/2026/03/Bild-8-Container-Manager-Projekt-erstellen-erfolgreich-abgeschlossen-300x221.png 300w, https://www.foundic.org/wp-content/uploads/2026/03/Bild-8-Container-Manager-Projekt-erstellen-erfolgreich-abgeschlossen-768x565.png 768w, https://www.foundic.org/wp-content/uploads/2026/03/Bild-8-Container-Manager-Projekt-erstellen-erfolgreich-abgeschlossen.png 1222w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 8 &#8211; Container Manager &#8211; Projekt erstellen &#8211; erfolgreich abgeschlossen</figcaption></figure>



<h3 class="wp-block-heading">Schritt 1.8: Telegram testen</h3>



<p>Beim allerersten Mal antwortet dein Bot mit einem&nbsp;<strong>Pairing-Code</strong>. Pairing bedeutet: Du bestätigst einmalig, dass dieses Gerät (dein Smartphone) berechtigt ist, mit dem Bot zu chatten. Ohne diese Bestätigung antwortet der Bot nicht.<br>Schreibe dem Bot irgendetwas in Telegram. Er antwortet mit einem Code. Dann in der SSH-Sitzung:</p>



<pre class="wp-block-code"><code>cd /volume1/docker/openclaw
docker compose run --rm openclaw-cli pairing approve telegram &lt;CODE&gt;</code></pre>



<p>Den Code aus der Telegram-Nachricht einsetzen. Danach funktioniert der Chat ganz normal.<br><strong>Soll-Ergebnis:</strong>&nbsp;Der Bot antwortet auf deine nächste Nachricht mit einer sinnvollen KI-Antwort.</p>



<h2 class="wp-block-heading">Teil 2: Optionale Erweiterungen</h2>



<p>Die Grundinstallation läuft. OpenClaw antwortet per Telegram. Was jetzt kommt, ist optional – aber empfehlenswert.</p>



<h3 class="wp-block-heading">Optional A: Web-Oberfläche per SSH-Tunnel</h3>



<p>Zusätzlich zu Telegram gibt es eine browserbasierte Oberfläche. Sie ist bewusst nicht direkt im Netzwerk erreichbar – der Zugriff läuft über einen SSH-Tunnel. Das ist kein Umweg, sondern Absicht: Die Web-UI soll nicht offen im Heimnetz hängen.</p>



<p><strong>SSH-Tunnel öffnen</strong>&nbsp;(auf dem Mac, neues Terminalfenster):</p>



<pre class="wp-block-code"><code>ssh -L 18789:127.0.0.1:18789 dein-benutzername@IP_der_Diskstation</code></pre>



<p>Das Kommando leitet deinen lokalen Port 18789 verschlüsselt durch SSH an Port 18789 auf der DiskStation weiter. Solange dieses Terminalfenster offen ist, funktioniert der Tunnel.</p>



<p><strong>Dann im Browser aufrufen</strong>&nbsp;(eigenen Token aus Schritt 1.6 einsetzen):</p>



<pre class="wp-block-code"><code>http:&#47;&#47;localhost:18789#token=2bbea678f.........................67003d38</code></pre>



<p>Verwende&nbsp;<code>localhost</code>, nicht&nbsp;<code>127.0.0.1</code>. Das ist kein Tippfehler – es macht technisch einen Unterschied bei der Erkennung des Tokens. Der Token muss direkt hinter dem&nbsp;<code>#</code>&nbsp;stehen, ohne Leerzeichen.</p>



<p><strong>Falls „channel: open failed: administratively prohibited&#8220; kommt:</strong></p>



<p>SSH Port-Forwarding ist auf der DiskStation deaktiviert. Einmalig freischalten (andere Terminal-Sitzung, als root):</p>



<pre class="wp-block-code"><code>sudo -i
echo "AllowTcpForwarding yes" &gt;&gt; /etc/ssh/sshd_config
sed -i '85s/AllowTcpForwarding no/AllowTcpForwarding yes/' /etc/ssh/sshd_config
systemctl restart sshd</code></pre>



<p>Falls&nbsp;<code>systemctl</code>&nbsp;nicht verfügbar ist:</p>



<pre class="wp-block-code"><code>synosystemctl restart sshd</code></pre>



<p>Dann SSH-Tunnel neu starten und wieder im Browser aufrufen.<br><strong>Falls „pairing required&#8220; angezeigt wird:</strong><br>Der Browser muss einmalig gepairt werden – genau wie Telegram in Schritt 1.8. Offene Pairing-Codes anzeigen:</p>



<pre class="wp-block-code"><code>sudo docker exec -it openclaw-gateway node /app/openclaw.mjs devices list</code></pre>



<p>Den Code aus der Spalte „Pending → Request → Code&#8220; notieren und bestätigen:</p>



<pre class="wp-block-code"><code>sudo docker exec -it openclaw-gateway node /app/openclaw.mjs devices approve DEIN_CODE</code></pre>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400831e03&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400831e03" class="wp-block-image aligncenter size-full wp-lightbox-container"><img loading="lazy" decoding="async" width="948" height="726" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/03/Bild-9-Browser-mit-Openclaw-pairen.png" alt="Bild 9 - Browser mit Openclaw pairen]" class="wp-image-1048" srcset="https://www.foundic.org/wp-content/uploads/2026/03/Bild-9-Browser-mit-Openclaw-pairen.png 948w, https://www.foundic.org/wp-content/uploads/2026/03/Bild-9-Browser-mit-Openclaw-pairen-300x230.png 300w, https://www.foundic.org/wp-content/uploads/2026/03/Bild-9-Browser-mit-Openclaw-pairen-768x588.png 768w" sizes="auto, (max-width: 948px) 100vw, 948px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 9 &#8211; Browser mit Openclaw pairen]</figcaption></figure>



<h3 class="wp-block-heading">Optional B: Netzwerk-Isolation härten</h3>



<p>Bisher kann der Container theoretisch alle Geräte in deinem Heimnetz erreichen – deinen Router, andere NAS-Geräte, Smart-Home-Systeme. Für einen KI-Agenten, der API-Anfragen ins Internet schickt, ist das ein unnötiges Risiko.</p>



<p><strong>Bernd:</strong>&nbsp;„Ich versteh nicht, warum das nötig sein soll. Die Fritzbox macht das doch schon.&#8220;<br><strong>Tanja:</strong>&nbsp;„Deine Fritzbox filtert Verbindungen von außen nach innen. Verbindungen vom Container in dein Netz sieht sie gar nicht – die laufen intern auf der NAS. Dafür brauchen wir iptables-Regeln direkt auf der DiskStation.&#8220;<br><strong>Ulf:</strong>&nbsp;„iptables – ist das wie die Schiedsrichterregeln?&#8220;<br><strong>Tanja:</strong>&nbsp;„Perfekter Vergleich! iptables ist das Regelwerk, das entscheidet, welche Datenpakete durchdürfen und welche direkt abgepfiffen werden.&#8220;<br><strong>Ulf:</strong>&nbsp;„Und DOCKER-USER?&#8220;<br><strong>Tanja:</strong>&nbsp;„DOCKER-USER ist die iptables-Kette, die Docker speziell für benutzerdefinierte Filterregeln vor der Container-Weiterleitung berücksichtigt. Wir schreiben unsere Regeln dorthin, damit sie Docker nicht überschreibt.&#8220;</p>



<p>Die zusätzlichen iptables-Regeln in diesem Abschnitt reduzieren das Risiko, dass ein kompromittierter Container interne Geräte im Heimnetz erreicht. Sie ersetzen jedoch keine VM-Isolation, kein Patch-Management und keine sorgfältige Prüfung der eingesetzten Container-Images.</p>



<h4 class="wp-block-heading">Schritt B.1: Firewall-Skript erstellen</h4>



<p>Das Skript arbeitet in drei Phasen:</p>



<ul class="wp-block-list">
<li><strong>Phase 1:</strong>&nbsp;Löscht eigene Regeln, falls das Skript schon einmal gelaufen ist.</li>



<li><strong>Phase 2:</strong>&nbsp;Baut IPv4-Regeln neu auf.</li>



<li><strong>Phase 3:</strong>&nbsp;Ergänzt IPv6-Regeln.<br>Das Skript ist&nbsp;<strong>idempotent</strong>&nbsp;– du kannst es beliebig oft ausführen, es baut immer sauber neu auf.</li>
</ul>



<pre class="wp-block-code"><code>cat &gt; /volume1/docker/openclaw/openclaw-firewall.sh &lt;&lt; 'DATEIENDE'
#!/bin/bash
# =============================================================================
# openclaw-firewall.sh
# Netzwerk-Isolations-Skript für OpenClaw auf Synology DS1621+
# =============================================================================
# Kompatibel mit Synology DSM iptables 1.8.x (kein comment-Modul verfügbar).
#
# Blockiert ausgehenden Traffic vom OpenClaw-Container zu allen privaten
# und reservierten IPv4-Netzen. Internet-Zugang bleibt erlaubt.
# DNS läuft über öffentliche Server (1.1.1.1 / 8.8.8.8, gesetzt in
# docker-compose.yml), da der Router-DNS durch die Regeln blockiert wird.
#
# Idempotent: Löscht zuerst alle eigenen Regeln (per exakter Spezifikation),
# dann baut es die Regeln in definierter Reihenfolge neu auf.
# Kann beliebig oft ausgeführt werden.
#
# IPv6: Blockiert ULA (fc00::/7) und Link-Local (fe80::/10) global für den
# gesamten Docker-Forward-Traffic, da dem Container kein festes IPv6-Präfix
# zugewiesen ist. Falls du später andere Container mit IPv6 betreiben willst,
# diese Regeln anpassen.
#
# Verwendung:
#   Als Boot-Aufgabe im Synology Aufgabenplaner einrichten:
#   bash /volume1/docker/openclaw/openclaw-firewall.sh
# =============================================================================

sleep 30

DOCKER_SUBNET="172.30.0.0/24"   # Muss mit compose.yaml übereinstimmen

# ─────────────────────────────────────────────────────────────────────────────
# Phase 1: Alle eigenen Regeln entfernen (exakte Spezifikation)
# ─────────────────────────────────────────────────────────────────────────────

# IPv4
iptables -D DOCKER-USER -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT 2&gt;/dev/null
iptables -D DOCKER-USER -s "$DOCKER_SUBNET" -d 192.168.0.0/16 -j DROP 2&gt;/dev/null
iptables -D DOCKER-USER -s "$DOCKER_SUBNET" -d 10.0.0.0/8 -j DROP 2&gt;/dev/null
iptables -D DOCKER-USER -s "$DOCKER_SUBNET" -d 172.16.0.0/12 -j DROP 2&gt;/dev/null
iptables -D DOCKER-USER -s "$DOCKER_SUBNET" -d 169.254.0.0/16 -j DROP 2&gt;/dev/null
iptables -D DOCKER-USER -s "$DOCKER_SUBNET" -d 100.64.0.0/10 -j DROP 2&gt;/dev/null

# IPv6
ip6tables -D DOCKER-USER -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT 2&gt;/dev/null
ip6tables -D DOCKER-USER -d fc00::/7 -j DROP 2&gt;/dev/null
ip6tables -D DOCKER-USER -d fe80::/10 -j DROP 2&gt;/dev/null

# ─────────────────────────────────────────────────────────────────────────────
# Phase 2: IPv4-Regeln in DOCKER-USER aufbauen
# ─────────────────────────────────────────────────────────────────────────────

# Position 1: Antwortpakete von erlaubten Verbindungen durchlassen
iptables -I DOCKER-USER 1 \
  -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Position 2-6: Private und reservierte Netze blockieren
iptables -I DOCKER-USER 2 \
  -s "$DOCKER_SUBNET" -d 192.168.0.0/16 -j DROP

iptables -I DOCKER-USER 3 \
  -s "$DOCKER_SUBNET" -d 10.0.0.0/8 -j DROP

iptables -I DOCKER-USER 4 \
  -s "$DOCKER_SUBNET" -d 172.16.0.0/12 -j DROP

iptables -I DOCKER-USER 5 \
  -s "$DOCKER_SUBNET" -d 169.254.0.0/16 -j DROP

iptables -I DOCKER-USER 6 \
  -s "$DOCKER_SUBNET" -d 100.64.0.0/10 -j DROP

# RETURN: nur hinzufügen wenn keiner existiert
if ! iptables -L DOCKER-USER -n 2&gt;/dev/null | grep -q "RETURN"; then
  iptables -A DOCKER-USER -j RETURN
fi

# ─────────────────────────────────────────────────────────────────────────────
# Phase 3: IPv6-Regeln (falls DOCKER-USER in ip6tables existiert)
# ─────────────────────────────────────────────────────────────────────────────

if ip6tables -L DOCKER-USER -n &gt;/dev/null 2&gt;&amp;1; then
  ip6tables -I DOCKER-USER 1 \
    -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

  ip6tables -I DOCKER-USER 2 \
    -d fc00::/7 -j DROP

  ip6tables -I DOCKER-USER 3 \
    -d fe80::/10 -j DROP

  if ! ip6tables -L DOCKER-USER -n 2&gt;/dev/null | grep -q "RETURN"; then
    ip6tables -A DOCKER-USER -j RETURN
  fi
fi

# ─────────────────────────────────────────────────────────────────────────────
# Ausgabe
# ─────────────────────────────────────────────────────────────────────────────
logger "openclaw-firewall: DOCKER-USER Regeln aktiv fuer $DOCKER_SUBNET"

echo ""
echo "========================================"
echo " OpenClaw Netzwerk-Isolation aktiviert"
echo "========================================"
echo ""
echo "IPv4 DOCKER-USER:"
iptables -L DOCKER-USER -n -v --line-numbers
echo ""

if ip6tables -L DOCKER-USER -n &gt;/dev/null 2&gt;&amp;1; then
  echo "IPv6 DOCKER-USER:"
  ip6tables -L DOCKER-USER -n -v --line-numbers
  echo ""
fi

echo "Erwartete Reihenfolge:"
echo "  1  ACCEPT     ctstate RELATED,ESTABLISHED"
echo "  2  DROP       172.30.0.0/24 -&gt; 192.168.0.0/16"
echo "  3  DROP       172.30.0.0/24 -&gt; 10.0.0.0/8"
echo "  4  DROP       172.30.0.0/24 -&gt; 172.16.0.0/12"
echo "  5  DROP       172.30.0.0/24 -&gt; 169.254.0.0/16"
echo "  6  DROP       172.30.0.0/24 -&gt; 100.64.0.0/10"
echo "  7  RETURN"
DATEIENDE</code></pre>



<p>Dann das Skript ausführbar machen:</p>



<pre class="wp-block-code"><code># Zu root wechseln
sudo -i

chmod +x /volume1/docker/openclaw/openclaw-firewall.sh</code></pre>



<p><strong>Welche Netze werden blockiert?</strong></p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Bereich</th><th>Protokoll</th><th>Was ist das?</th></tr></thead><tbody><tr><td><code>192.168.0.0/16</code></td><td>IPv4</td><td>Heimnetze (Fritzbox, etc.)</td></tr><tr><td><code>10.0.0.0/8</code></td><td>IPv4</td><td>Firmennetzwerke, VPNs</td></tr><tr><td><code>172.16.0.0/12</code></td><td>IPv4</td><td>Weitere private Netze</td></tr><tr><td><code>169.254.0.0/16</code></td><td>IPv4</td><td>Link-Local (mDNS-Geräte, APIPA)</td></tr><tr><td><code>100.64.0.0/10</code></td><td>IPv4</td><td>CGNAT (manche Provider/VPNs)</td></tr><tr><td><code>fc00::/7</code></td><td>IPv6 (global)</td><td>ULA (IPv6-Äquivalent zu privaten Netzen)</td></tr><tr><td><code>fe80::/10</code></td><td>IPv6 (global)</td><td>IPv6 Link-Local</td></tr></tbody></table></figure>



<p><strong>Hinweis IPv6:</strong>&nbsp;Die IPv6-Regeln gelten für den gesamten Docker-Forward-Traffic auf der DiskStation, nicht nur für OpenClaw. Falls du später andere Container mit IPv6 betreiben willst, müssen diese Regeln angepasst werden.</p>



<h4 class="wp-block-heading">Schritt B.2: Firewall als Boot-Aufgabe einrichten</h4>



<p>Die iptables-Regeln sind flüchtig – ein Neustart löscht sie. Damit sie nach jedem Hochfahren automatisch aktiv sind:</p>



<ol class="wp-block-list">
<li>Öffne:&nbsp;<strong>Systemsteuerung → Dienste → Aufgabenplaner</strong>.</li>



<li>Klicke&nbsp;<strong>Erstellen → Ausgelöste Aufgabe → Benutzerdefiniertes Skript</strong>.</li>



<li><strong>Reiter Allgemein:</strong>
<ul class="wp-block-list">
<li>Aufgabe:&nbsp;<code>OpenClaw Netzwerk-Isolation</code></li>



<li>Benutzer:&nbsp;<code>root</code></li>



<li>Ereignis:&nbsp;<code>Hochfahren</code></li>
</ul>
</li>



<li><strong>Reiter Aufgabeneinstellungen:</strong>&nbsp;In das Textfeld eingeben:</li>
</ol>



<pre class="wp-block-code"><code>   bash /volume1/docker/openclaw/openclaw-firewall.sh</code></pre>



<ol start="5" class="wp-block-list">
<li>Klicke&nbsp;<strong>OK</strong>&nbsp;und bestätige die Warnung.</li>
</ol>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400832835&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400832835" class="wp-block-image aligncenter size-full wp-lightbox-container"><img loading="lazy" decoding="async" width="537" height="557" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/03/Bild-10-Diskstation-Aufgabenplaner-Reiter-Allgemein.png" alt="Bild 10 - Diskstation - Aufgabenplaner - Reiter Allgemein" class="wp-image-1050" srcset="https://www.foundic.org/wp-content/uploads/2026/03/Bild-10-Diskstation-Aufgabenplaner-Reiter-Allgemein.png 537w, https://www.foundic.org/wp-content/uploads/2026/03/Bild-10-Diskstation-Aufgabenplaner-Reiter-Allgemein-289x300.png 289w" sizes="auto, (max-width: 537px) 100vw, 537px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 10 &#8211; Diskstation &#8211; Aufgabenplaner &#8211; Reiter Allgemein</figcaption></figure>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400832e27&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400832e27" class="wp-block-image aligncenter size-full wp-lightbox-container"><img loading="lazy" decoding="async" width="538" height="559" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/03/Bild-11-Diskstation-Aufgabenplaner-Reiter-Aufgabeneinstellungen.png" alt="Bild 11 - Diskstation - Aufgabenplaner - Reiter Aufgabeneinstellungen" class="wp-image-1051" srcset="https://www.foundic.org/wp-content/uploads/2026/03/Bild-11-Diskstation-Aufgabenplaner-Reiter-Aufgabeneinstellungen.png 538w, https://www.foundic.org/wp-content/uploads/2026/03/Bild-11-Diskstation-Aufgabenplaner-Reiter-Aufgabeneinstellungen-289x300.png 289w" sizes="auto, (max-width: 538px) 100vw, 538px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 11 &#8211; Diskstation &#8211; Aufgabenplaner &#8211; Reiter Aufgabeneinstellungen</figcaption></figure>



<h4 class="wp-block-heading">Schritt B.3: Firewall sofort aktivieren</h4>



<pre class="wp-block-code"><code>bash /volume1/docker/openclaw/openclaw-firewall.sh</code></pre>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400833471&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400833471" class="wp-block-image aligncenter size-full wp-lightbox-container"><img loading="lazy" decoding="async" width="844" height="307" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/03/Bild-12-Terminal-OpenClaw-Netzwerk-Isolation-aktiviert.png" alt="Bild 12 - Terminal - OpenClaw Netzwerk-Isolation aktiviert" class="wp-image-1053" srcset="https://www.foundic.org/wp-content/uploads/2026/03/Bild-12-Terminal-OpenClaw-Netzwerk-Isolation-aktiviert.png 844w, https://www.foundic.org/wp-content/uploads/2026/03/Bild-12-Terminal-OpenClaw-Netzwerk-Isolation-aktiviert-300x109.png 300w, https://www.foundic.org/wp-content/uploads/2026/03/Bild-12-Terminal-OpenClaw-Netzwerk-Isolation-aktiviert-768x279.png 768w" sizes="auto, (max-width: 844px) 100vw, 844px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 12 &#8211; Terminal &#8211; OpenClaw Netzwerk-Isolation aktiviert</figcaption></figure>



<p><strong>Soll-Ergebnis – Regeln prüfen:</strong></p>



<pre class="wp-block-code"><code>iptables -L DOCKER-USER -n -v --line-numbers</code></pre>



<p>Erwartete Ausgabe:</p>



<pre class="wp-block-code"><code>num   target     prot  source           destination
1     ACCEPT     all   0.0.0.0/0        0.0.0.0/0        ctstate RELATED,ESTABLISHED
2     DROP       all   172.30.0.0/24    192.168.0.0/16
3     DROP       all   172.30.0.0/24    10.0.0.0/8
4     DROP       all   172.30.0.0/24    172.16.0.0/12
5     DROP       all   172.30.0.0/24    169.254.0.0/16
6     DROP       all   172.30.0.0/24    100.64.0.0/10
7     RETURN     all   0.0.0.0/0        0.0.0.0/0</code></pre>



<p>Falls die Reihenfolge nicht stimmt: Skript nochmals ausführen – es räumt zuerst auf und baut sauber neu.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400833b6a&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400833b6a" class="wp-block-image aligncenter size-full wp-lightbox-container"><img loading="lazy" decoding="async" width="798" height="253" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/03/Bild-13-Terminal-OpenClaw-Netzwerk-iptables.png" alt="Bild 13 - Terminal - OpenClaw Netzwerk - iptables" class="wp-image-1054" srcset="https://www.foundic.org/wp-content/uploads/2026/03/Bild-13-Terminal-OpenClaw-Netzwerk-iptables.png 798w, https://www.foundic.org/wp-content/uploads/2026/03/Bild-13-Terminal-OpenClaw-Netzwerk-iptables-300x95.png 300w, https://www.foundic.org/wp-content/uploads/2026/03/Bild-13-Terminal-OpenClaw-Netzwerk-iptables-768x243.png 768w" sizes="auto, (max-width: 798px) 100vw, 798px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 13 &#8211; Terminal &#8211; OpenClaw Netzwerk &#8211; iptables</figcaption></figure>



<h4 class="wp-block-heading">Isolation testen:</h4>



<pre class="wp-block-code"><code># Internet muss funktionieren:
sudo docker exec openclaw-gateway node -e "fetch('https://api.telegram.org').then(r=&gt;console.log('OK',r.status)).catch(e=&gt;console.log('FEHLER',e.message))"

# Heimnetz muss blockiert sein:
sudo docker exec openclaw-gateway node -e "fetch('http://192.168.2.1',{signal:AbortSignal.timeout(3000)}).then(r=&gt;console.log('OFFEN!',r.status)).catch(e=&gt;console.log('BLOCKIERT (gut!)'))"

# Firewall-Regeln prüfen:
sudo iptables -L DOCKER-USER -n -v --line-numbers</code></pre>



<p>Erwartetes Ergebnis: Internet antwortet mit&nbsp;<code>OK 200</code>, Heimnetz meldet&nbsp;<code>BLOCKIERT (gut!)</code>.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e44008341bf&quot;}" data-wp-interactive="core/image" data-wp-key="69e44008341bf" class="wp-block-image aligncenter size-full wp-lightbox-container"><img loading="lazy" decoding="async" width="952" height="291" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/03/Bild-14-Isolation-testen-Ergebnis.png" alt="Bild 13 - Terminal - OpenClaw Netzwerk - iptables" class="wp-image-1055" srcset="https://www.foundic.org/wp-content/uploads/2026/03/Bild-14-Isolation-testen-Ergebnis.png 952w, https://www.foundic.org/wp-content/uploads/2026/03/Bild-14-Isolation-testen-Ergebnis-300x92.png 300w, https://www.foundic.org/wp-content/uploads/2026/03/Bild-14-Isolation-testen-Ergebnis-768x235.png 768w" sizes="auto, (max-width: 952px) 100vw, 952px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 13 &#8211; Terminal &#8211; OpenClaw Netzwerk &#8211; iptables</figcaption></figure>



<h3 class="wp-block-heading">Optional C: Playwright-Browser nachrüsten</h3>



<p>Bisher kommuniziert OpenClaw über APIs und Text. Mit einem eingebetteten Playwright-Browser kann er auch echte Webseiten laden, scrollen, Formulare ausfüllen und JavaScript-Rendering nutzen.</p>



<p><strong>Ulf:</strong>&nbsp;„OpenClaw soll selbst surfen können? Wie ein Libero, der plötzlich stürmt?&#8220;<br><strong>Tanja:</strong>&nbsp;„Genau so! Das LLM plant, Playwright führt aus. OpenClaw kann damit Inhalte aus dynamischen Seiten lesen, die über einfache HTTP-Requests nicht zugänglich sind.&#8220;<br><strong>Bernd:</strong>&nbsp;„Ich hab einfach den System-Chromium genommen. Lief nicht. Dreimal probiert. Nie funktioniert.&#8220;<br><strong>Tanja:</strong>&nbsp;„Deshalb bringt man die Browser-Binaries mit dem Container mit. Dann klappt es reproduzierbar – immer.&#8220;</p>



<p>Ein Playwright-Browser im Docker-Container bringt seine eigenen Browser-Binaries und Abhängigkeiten mit. Das vermeidet Konflikte mit System-Bibliotheken und Versionsinkompatibilitäten.</p>



<h4 class="wp-block-heading">Schritt C.1: Dockerfile anlegen</h4>



<p>Erstelle&nbsp;<code>/volume1/docker/openclaw/Dockerfile</code>:</p>



<pre class="wp-block-code"><code>FROM ghcr.io/openclaw/openclaw:latest

USER root

# Systembibliotheken für Chromium / Playwright
RUN apt-get update &amp;&amp; apt-get install -y \
    libnspr4 \
    libnss3 \
    libatk1.0-0 \
    libatk-bridge2.0-0 \
    libcups2 \
    libdrm2 \
    libxkbcommon0 \
    libxcomposite1 \
    libxdamage1 \
    libxfixes3 \
    libxrandr2 \
    libgbm1 \
    libasound2 \
    ca-certificates \
    wget \
    &amp;&amp; rm -rf /var/lib/apt/lists/*

USER node</code></pre>



<p>Dann in der&nbsp;<code>compose.yaml</code>&nbsp;bei&nbsp;<strong>beiden</strong>&nbsp;Diensten (<code>openclaw-gateway</code>&nbsp;und&nbsp;<code>openclaw-cli</code>) die&nbsp;<code>image</code>-Zeile ersetzen:</p>



<pre class="wp-block-code"><code># Vorher:
image: ghcr.io/openclaw/openclaw:latest

# Nachher:
build:
  context: /volume1/docker/openclaw
  dockerfile: Dockerfile</code></pre>



<h4 class="wp-block-heading">Schritt C.2: Chromium installieren</h4>



<pre class="wp-block-code"><code>cd /volume1/docker/openclaw

sudo docker compose -p openclaw run --rm --entrypoint sh \
  -e PLAYWRIGHT_BROWSERS_PATH=/home/node/.openclaw/workspace/.browser \
  openclaw-cli -c 'mkdir -p /home/node/.openclaw/workspace/.browser &amp;&amp; \
  node /app/node_modules/playwright-core/cli.js install chromium'</code></pre>



<p><strong>Soll-Ergebnis – Installation prüfen:</strong></p>



<pre class="wp-block-code"><code>sudo docker exec -it openclaw-gateway sh -c 'ls -la /home/node/.openclaw/workspace/.browser'</code></pre>



<p>Du solltest einen Ordner wie&nbsp;<code>chromium-1208</code>&nbsp;sehen. Dann den Browser-Pfad testen:</p>



<pre class="wp-block-code"><code>sudo docker exec -it openclaw-gateway sh -c '/home/node/.openclaw/workspace/.browser/chromium-1208/chrome-linux64/chrome --version'</code></pre>



<p>Eine ausgegebene Chrome-Versionsnummer bedeutet: Chromium ist korrekt installiert.<br>Der Ordnername (z.B.&nbsp;<code>chromium-1208</code>) hängt von der Playwright-Version ab. Prüfe ihn immer mit&nbsp;<code>ls</code>&nbsp;– er kann sich bei Updates ändern.</p>



<h4 class="wp-block-heading">Schritt C.3: Browser-Pfad in openclaw.json setzen</h4>



<p>Öffne&nbsp;<code>/volume1/docker/openclaw/config/openclaw.json</code>&nbsp;und füge den&nbsp;<code>browser</code>-Block ein:</p>



<pre class="wp-block-code"><code>"browser": {
  "enabled": true,
  "defaultProfile": "openclaw",
  "headless": true,
  "noSandbox": true,
  "executablePath": "/home/node/.openclaw/workspace/.browser/chromium-1208/chrome-linux64/chrome",
  "profiles": {
    "openclaw": {
      "cdpPort": 18800,
      "color": "#FF4500"
    }
  }
}</code></pre>



<h4 class="wp-block-heading">Schritt C.4: Testen</h4>



<pre class="wp-block-code"><code>sudo docker exec -it openclaw-gateway sh -c '/home/node/.openclaw/workspace/.browser/chromium-1208/chrome-linux64/chrome --version'</code></pre>



<p>Dann in OpenClaw (per Telegram oder Web-UI):</p>



<pre class="wp-block-code"><code>Verwende das Browser-Profil "openclaw" und öffne https://example.com.</code></pre>



<p>Wenn OpenClaw antwortet und den Seiteninhalt beschreibt, ist alles korrekt eingerichtet.</p>



<h2 class="wp-block-heading">Nützliche Befehle &#8211; der Spickzettel</h2>



<p><strong>Ulf:</strong>&nbsp;„Kann ich die ganzen Befehle irgendwo nachschlagen, ohne die ganze Anleitung nochmal zu lesen?&#8220;<br><strong>Tanja:</strong>&nbsp;„Genau dafür gibt es diese Tabelle.&#8220;</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Was</th><th>Befehl</th></tr></thead><tbody><tr><td><strong>Stoppen</strong></td><td>Container Manager → Projekt → openclaw → Stoppen</td></tr><tr><td><strong>Starten</strong></td><td>Container Manager → Projekt → openclaw → Starten</td></tr><tr><td><strong>Logs</strong></td><td>Container Manager → Projekt → openclaw → Logs</td></tr><tr><td><strong>Stoppen (SSH)</strong></td><td><code>cd /volume1/docker/openclaw &amp;&amp; docker compose down</code></td></tr><tr><td><strong>Starten (SSH)</strong></td><td><code>cd /volume1/docker/openclaw &amp;&amp; docker compose up -d openclaw-gateway</code></td></tr><tr><td><strong>Logs (SSH)</strong></td><td><code>docker logs openclaw-gateway --tail 20</code></td></tr><tr><td><strong>Aktualisieren</strong></td><td><code>cd /volume1/docker/openclaw &amp;&amp; docker compose pull &amp;&amp; docker compose down &amp;&amp; docker compose up -d openclaw-gateway</code></td></tr><tr><td><strong>SSH-Tunnel</strong>&nbsp;(vom Mac)</td><td><code>ssh -L 18789:127.0.0.1:18789 Teddy@192.168.2.10</code></td></tr><tr><td><strong>Firewall prüfen</strong></td><td><code>sudo iptables -L DOCKER-USER -n -v --line-numbers</code></td></tr><tr><td><strong>Firewall neu laden</strong></td><td><code>sudo bash /volume1/docker/openclaw/openclaw-firewall.sh</code></td></tr></tbody></table></figure>



<h2 class="wp-block-heading">Fehlerbehebung</h2>



<p>Hier sind die häufigsten Probleme und ihre Lösungen. Bernd hat mindestens drei davon bereits persönlich erlebt.</p>



<h3 class="wp-block-heading">Container startet nicht oder beendet sich sofort</h3>



<p><strong>Symptom:</strong>&nbsp;Container Manager meldet „unerwartet beendet&#8220;, Logs zeigen Fehler.<br><strong>Prüfen:</strong></p>



<pre class="wp-block-code"><code>docker logs openclaw-gateway --tail 50</code></pre>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Fehlermeldung</th><th>Ursache</th><th>Lösung</th></tr></thead><tbody><tr><td><code>Missing config</code></td><td>Onboarding nicht abgeschlossen</td><td>Schritt 1.6 durchführen</td></tr><tr><td><code>non-loopback Control UI requires allowedOrigins</code></td><td><code>config set</code>-Befehl fehlt</td><td>Befehl am Ende von Schritt 1.6 nachholen</td></tr><tr><td><code>EACCES: permission denied</code></td><td>Ordnerrechte falsch</td><td><code>sudo chown -R 1000:1000 /volume1/docker/openclaw</code></td></tr><tr><td><code>pids_limit discarded</code></td><td>Synology-Kernel unterstützt es nicht</td><td>Harmlos, ignorieren</td></tr></tbody></table></figure>



<h3 class="wp-block-heading">Web-Oberfläche nicht erreichbar</h3>



<p><strong>Symptom:</strong>&nbsp;Browser zeigt leere Seite, Verbindung abgelehnt oder „pairing required&#8220;.<br><strong>Prüfen:</strong></p>



<pre class="wp-block-code"><code>docker ps --filter name=openclaw-gateway
docker logs openclaw-gateway --tail 50</code></pre>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Mögliche Ursache</th><th>Prüfbefehl / Lösung</th></tr></thead><tbody><tr><td>Container läuft nicht</td><td><code>docker compose up -d openclaw-gateway</code></td></tr><tr><td>SSH-Tunnel nicht aktiv</td><td><code>ssh -L 18789:127.0.0.1:18789 user@NAS_IP</code>&nbsp;im Terminal öffnen</td></tr><tr><td>Port-Forwarding deaktiviert</td><td>Fehler „administratively prohibited&#8220; → SSH-Forwarding freischalten (Schritt Optional A)</td></tr><tr><td><code>allowedOrigins</code>&nbsp;nicht gesetzt</td><td><code>docker compose run --rm openclaw-cli config set gateway.controlUi.allowedOrigins '["http://localhost:18789"]'</code></td></tr><tr><td>Browser noch nicht gepairt</td><td><code>devices list</code>&nbsp;und&nbsp;<code>devices approve</code>&nbsp;(Schritt Optional A)</td></tr><tr><td>Falsche URL</td><td><code>http://localhost:18789</code>&nbsp;– nicht&nbsp;<code>127.0.0.1</code>, nicht die NAS-IP</td></tr></tbody></table></figure>



<h3 class="wp-block-heading">Telegram antwortet nicht</h3>



<p><strong>Symptom:</strong>&nbsp;Bot bleibt stumm, keine Antwort auf Nachrichten.<br><strong>Prüfen:</strong></p>



<pre class="wp-block-code"><code>docker logs openclaw-gateway --tail 20</code></pre>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Mögliche Ursache</th><th>Lösung</th></tr></thead><tbody><tr><td>Pairing nicht abgeschlossen</td><td>Schritt 1.8 durchführen</td></tr><tr><td>Kein Internet</td><td>Folgenden Test ausführen (s.u.)</td></tr><tr><td>Falscher Bot-Token</td><td>Token im Onboarding neu eingeben (<code>configure</code>)</td></tr></tbody></table></figure>



<p><strong>Internet-Test:</strong></p>



<pre class="wp-block-code"><code>docker exec openclaw-gateway node -e "fetch('https://api.telegram.org').then(r=&gt;console.log('OK',r.status)).catch(e=&gt;console.log('FEHLER',e.message))"</code></pre>



<h3 class="wp-block-heading">Firewall-Regeln fehlen nach DSM-Update</h3>



<p><strong>Symptom:</strong>&nbsp;Internet-Zugriff vom Container ins Heimnetz ist wieder möglich.<br><strong>Prüfen:</strong></p>



<pre class="wp-block-code"><code>sudo iptables -L DOCKER-USER -n -v --line-numbers</code></pre>



<p>Falls die Liste leer oder unvollständig ist:</p>



<pre class="wp-block-code"><code>sudo bash /volume1/docker/openclaw/openclaw-firewall.sh</code></pre>



<p>Außerdem prüfen, ob die Boot-Aufgabe noch aktiv ist: Systemsteuerung → Aufgabenplaner.</p>



<h3 class="wp-block-heading">„Read-only file system&#8220;</h3>



<p><strong>Symptom:</strong>&nbsp;Fehlermeldung bei einem Skill oder Modul, das schreiben will.<br><strong>Temporäre Lösung:</strong>&nbsp;In der&nbsp;<code>compose.yaml</code>&nbsp;diese Zeile auskommentieren, Projekt neu starten:</p>



<pre class="wp-block-code"><code># read_only: true</code></pre>



<h3 class="wp-block-heading">&#8222;non-loopback Control UI requires allowedOrigins&#8220;</h3>



<p>Der Konfigurationsschritt aus Schritt 4.2 wurde übersprungen. Nachholen:</p>



<pre class="wp-block-code"><code>cd /volume1/docker/openclaw
docker compose run --rm openclaw-cli config set gateway.controlUi.allowedOrigins '&#91;"http://localhost:18789"]'</code></pre>



<h3 class="wp-block-heading">&#8222;Permission denied&#8220;</h3>



<p>Die Ordner gehören dem falschen Benutzer. Beheben mit:</p>



<pre class="wp-block-code"><code>sudo chown -R 1000:1000 /volume1/docker/openclaw</code></pre>



<h3 class="wp-block-heading">DNS / kein Internet</h3>



<p>Prüfe ob&nbsp;<code>dns: 1.1.1.1</code>&nbsp;und&nbsp;<code>dns: 8.8.8.8</code>&nbsp;in der&nbsp;<code>compose.yaml</code>&nbsp;vorhanden sind. Dann testen:</p>



<pre class="wp-block-code"><code>docker exec openclaw-gateway node -e "fetch('https://api.telegram.org').then(r=&gt;console.log('OK',r.status)).catch(e=&gt;console.log('FEHLER',e.message))"</code></pre>



<h3 class="wp-block-heading">&#8222;PIDs limit discarded&#8220; Warnung</h3>



<p>Harmlos. Der Synology-Kernel unterstützt das&nbsp;<code>pids_limit</code>-Feature nicht. Die Warnung kann ignoriert werden.</p>



<h2 class="wp-block-heading">Wartung und Updates</h2>



<p><strong>Container aktualisieren:</strong></p>



<pre class="wp-block-code"><code>cd /volume1/docker/openclaw
docker compose pull
docker compose down
docker compose up -d openclaw-gateway</code></pre>



<p><strong>Nach DSM-Updates:</strong>&nbsp;Firewall-Regeln prüfen und ggf. neu laden (siehe Fehlerbehebung oben).<br><strong>Konfiguration ändern</strong>&nbsp;(Modell, API-Key, Kanäle):</p>



<pre class="wp-block-code"><code>cd /volume1/docker/openclaw
docker compose run --rm openclaw-cli configure</code></pre>



<h2 class="wp-block-heading">Fertig!</h2>



<p><strong>Tanja:</strong>&nbsp;„Das war&#8217;s. OpenClaw läuft, die Firewall ist aktiv, Telegram ist verbunden. Du hast einen abgesicherten AI-Agenten auf deiner Heimnetz-NAS.&#8220;<br><strong>Ulf:</strong>&nbsp;„Und Bernd? Hat er seine VM noch?&#8220;<br><strong>Bernd:</strong>&nbsp;„Meine VM läuft übrigens auch. Aber der RAM war dann weg und das DSM-Update hat dann&#8230; ähm. Das ist eine andere Geschichte.&#8220;<br><strong>Tanja:</strong>&nbsp;„&#8230;war die VM weg. Ich weiß, Bernd. Ich weiß.&#8220;</p>



<p>Du hast in dieser Anleitung folgendes aufgebaut:</p>



<ul class="wp-block-list">
<li>Container Manager und SSH auf der DiskStation aktiviert</li>



<li>Ordnerstruktur für OpenClaw angelegt</li>



<li><code>compose.yaml</code>&nbsp;mit vollständigen Sicherheitseinstellungen erstellt und validiert</li>



<li>OpenClaw per interaktivem Onboarding konfiguriert</li>



<li>Telegram-Bot verbunden und gepairt</li>
</ul>



<p>Optional ergänzt:</p>



<ul class="wp-block-list">
<li>Web-Oberfläche per SSH-Tunnel zugänglich gemacht</li>



<li>Netzwerk-Isolation per iptables eingerichtet und als Boot-Aufgabe gespeichert</li>



<li>Playwright-Browser installiert</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://www.foundic.org/de/openclaw-synology-diskstation-installieren/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>KI-Telefonassistent selbst hosten: OpenAI Realtime API mit Fritz!Box, Asterisk &#038; n8n auf der Synology NAS</title>
		<link>https://www.foundic.org/de/ki-telefonassistent-openai-realtime-api-fritzbox-asterisk-synology-nas/</link>
					<comments>https://www.foundic.org/de/ki-telefonassistent-openai-realtime-api-fritzbox-asterisk-synology-nas/#respond</comments>
		
		<dc:creator><![CDATA[Michael Müller]]></dc:creator>
		<pubDate>Sun, 15 Mar 2026 19:38:00 +0000</pubDate>
				<category><![CDATA[Projekte]]></category>
		<guid isPermaLink="false">https://www.foundic.org/?p=859</guid>

					<description><![CDATA[Was du in diesem Tutorial baust, ist kein Anrufbeantworter. Es ist ein&#160;KI-Telefonassistent, der Anrufe vollautomatisch entgegennimmt, ein strukturiertes Gespräch führt – nach Name, Anliegen und Dringlichkeit fragt – und dir danach eine fertige E-Mail-Zusammenfassung schickt. Alles in natürlicher Sprache, auf Deutsch. Das Ganze läuft auf deiner&#160;Synology NAS&#160;zuhause, ohne Cloud-Abhängigkeiten für die Infrastruktur. Als Telefonanlage dient [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Was du in diesem Tutorial baust, ist kein Anrufbeantworter. Es ist ein&nbsp;<strong>KI-Telefonassistent</strong>, der Anrufe vollautomatisch entgegennimmt, ein strukturiertes Gespräch führt – nach Name, Anliegen und Dringlichkeit fragt – und dir danach eine fertige E-Mail-Zusammenfassung schickt. Alles in natürlicher Sprache, auf Deutsch.</p>



<p>Das Ganze läuft auf deiner&nbsp;<strong>Synology NAS</strong>&nbsp;zuhause, ohne Cloud-Abhängigkeiten für die Infrastruktur. Als Telefonanlage dient die Fritz!Box 7590, als Telefonie-Server Asterisk im Docker-Container, als KI-Gehirn die OpenAI Realtime API. Die Automatisierung übernimmt n8n.</p>



<p>Klingt komplex? An einigen Stellen ist es das auch, diese Anleitung führt dich aber Schritt für Schritt durch. Mit SSH-Grundkenntnissen und etwas Geduld ist das Ergebnis nachbaubar.</p>



<p><strong>Um diese Anleitung verständlicher zu machen, begleiten dich drei Personen:</strong><br>Die typischen Büro-Charaktere: Die kompetente IT-Kollegin, der selbsternannte Experte und der ehrliche Anfänger. Diese drei Perspektiven helfen dir, typische Stolperfallen zu erkennen.</p>



<p><strong>Tanja</strong> ist die IT-Expertin. Sie weiß, wie es funktioniert, erklärt geduldig und strukturiert und lässt sich von schlechten Ratschlägen nicht aus der Ruhe bringen. Wenn du eine Frage hast, hat Tanja die Antwort.<br><strong>Bernd</strong> ist der selbsternannte „Experte“, der alles besser weiß – und meistens falsch liegt. Seine Abkürzungen und sein Halbwissen führen regelmäßig zu Problemen. Er steht für alle gefährlichen Mythen und schlechten Praktiken, die du vermeiden solltest.<br><strong>Ulf</strong> ist der Lernende, genau wie du. Er stellt die Fragen, die dir im Kopf herumschwirren, und braucht manchmal einen Vergleich aus dem Alltag, um IT zu verstehen. Wenn Ulf etwas nicht versteht, ist das völlig in Ordnung, dafür ist Tanja da.</p>



<p><strong>&#8222;Und… Action!&#8220;</strong></p>



<p><strong>Donnerstagabend. Büro. Ulf starrt auf sein Handy.</strong><br><strong>Ulf</strong>: „Schon wieder eine verpasste Anruf-Benachrichtigung. Keine Nachricht. Keine Nummer. Nix.&#8220;<br><strong>Bernd</strong> ohne aufzuschauen: „Ruf zurück&#8220;,<br><strong>Ulf</strong>: „Ich kenn die Nummer nicht. Und wenn ich zurückruf, ist besetzt. Oder niemand geht ran. Oder &#8212; &#8212; &#8211;&#8222;<br><strong>Bernd</strong>: „Ich hab das gelöst, Anrufbeantworter. Ganz klassisch. ‚Hinterlassen Sie eine Nachricht nach dem Piepton.&#8216; Fertig.&#8220;<br><strong>Tanja</strong> legt ihren Stift hin. „Und wie viele Leute hinterlassen heutzutage noch Nachrichten auf einem Anrufbeantworter?&#8220;<br><strong>Bernd</strong> überlegt. „Na… Oma.&#8220;<br><strong>Tanja</strong>: „Genau.&#8220;</p>



<h2 class="wp-block-heading">1 Technische Beschreibung</h2>



<h3 class="wp-block-heading">1.1 Was macht dieses Projekt?</h3>



<p><strong>Ulf</strong> fragt: „Also die KI geht ans Telefon und redet mit dem Anrufer?&#8220;,<br><strong>Tanja</strong>: „Genau, sie begrüßt ihn, fragt nach seinem Namen, hört sich das Anliegen an, klärt wie dringend es ist und verabschiedet sich. Alles auf Deutsch, alles in natürlicher Sprache.&#8220;<br><strong>Ulf</strong>: „Und dann?&#8220;<br><strong>Tanja</strong>: „Und dann bekommst du eine E-Mail mit dem kompletten Gesprächsverlauf. Wer hat angerufen, was wollte die Person, wie dringend war es.&#8220;<br><strong>Bernd</strong> lehnt sich vor: „Ich hätte da einfach einen billigen Anrufbeantworter hingestellt.&#8220;<br><strong>Tanja</strong>: „Hattest du. Der hat nichts aufgenommen, weil der Piepton zu leise war.&#8220;<br>Bernd sagt nichts mehr.</p>



<p>Der KI-Assistent übernimmt Anrufe auf deiner Festnetznummer vollautomatisch. Er begrüßt den Anrufer freundlich, fragt nach Name und Anliegen, klärt die Dringlichkeit und verabschiedet sich in natürlichem Deutsch, ohne roboterhafte Pausen. Wenige Sekunden nach dem Auflegen landet eine vollständige Zusammenfassung in deinem Posteingang.</p>



<h3 class="wp-block-heading">1.2 Warum diese Architektur?</h3>



<p><strong>Ulf</strong>: „Moment, kann die Fritz!Box nicht einfach direkt mit OpenAI reden? Warum brauchen wir drei Systeme dazwischen?&#8220;<br><strong>Tanja</strong>: „Gute Frage. Die Fritz!Box spricht SIP – das ist das klassische Telefonie-Protokoll. OpenAI spricht WebSocket – das ist ein modernes Streaming-Protokoll. Die beiden verstehen sich nicht direkt. Wir brauchen einen Übersetzer.&#8220;<br><strong>Ulf</strong>: „Asterisk?&#8220;<br><strong>Tanja</strong>: „Asterisk ist der Übersetzer auf der Telefonie-Seite. Und das Node.js-Relay ist die Brücke zu OpenAI. Zusammen bilden sie den Verbindungskanal.&#8220;<br><strong>Ulf</strong>: „Das ist wie beim Fußball, die Fritz!Box ist der Torwart, der den Ball abschlägt. Asterisk ist der defensive Mittelfeldspieler, der ihn annimmt. Und das Relay ist der Spielmacher, der ihn zu OpenAI weiterleitet.&#8220;<br>Kurze Stille.<br><strong>Tanja</strong>: „Das ist, überraschend präzise.&#8220;</p>



<p>Die Fritz!Box ist ein reines Telefon-Gateway – sie versteht kein WebSocket, das OpenAI für die Realtime API benötigt. Asterisk übernimmt daher die Rolle des Vermittlers: Er nimmt das klassische SIP/RTP-Telefonsignal entgegen und reicht es an das Node.js-Relay weiter. Das Relay öffnet seinerseits eine WebSocket-Verbindung zu OpenAI und streamt das Audio bidirektional.<br>Der vollständige Signalweg:</p>



<pre class="wp-block-code"><code>Telefon → FritzBox (SIP) → Asterisk (Docker) → &#91;ARI/Node.js Relay] → WebSocket → api.openai.com:443</code></pre>



<p>OpenAI übernimmt dabei die komplette Gesprächsintelligenz: Spracherkennung, KI-Antworten und Text-to-Speech in einem einzigen Modell mit sehr niedriger Latenz. Nach dem Gespräch sendet das Relay das Transkript per Webhook an n8n, das daraus eine formatierte E-Mail erstellt.</p>



<h3 class="wp-block-heading">1.3 Technologie-Stack</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Komponente</th><th>Rolle</th></tr></thead><tbody><tr><td><strong>Fritz!Box 7590</strong></td><td>Telefon-Gateway: nimmt Festnetzanruf entgegen, leitet per SIP weiter</td></tr><tr><td><strong>Asterisk 20 (Docker)</strong></td><td>Telefonie-Server: SIP-Registrierung, Anrufsteuerung via ARI</td></tr><tr><td><strong>Node.js Relay (Docker)</strong></td><td>Brücke: wandelt RTP-Audio in WebSocket-Stream für OpenAI um</td></tr><tr><td><strong>OpenAI Realtime API</strong></td><td>KI-Gehirn: Spracherkennung, Dialog, Text-to-Speech in Echtzeit</td></tr><tr><td><strong>n8n (Docker)</strong></td><td>Automatisierung: empfängt Webhook, erstellt und versendet E-Mail</td></tr><tr><td><strong>Synology NAS</strong></td><td>Host: läuft alle Docker-Container, immer eingeschaltet</td></tr></tbody></table></figure>



<h3 class="wp-block-heading">1.4 Voraussetzungen</h3>



<p>Bevor du loslegst – ein ehrlicher Check. Du brauchst:<br><strong>Hardware:</strong></p>



<ul class="wp-block-list">
<li>Synology NAS mit&nbsp;<strong>Intel-CPU</strong>&nbsp;(z. B. DS1621xs+, DS1621+, DS923+, DS720+ oder vergleichbar) &#8211; ARM-Prozessoren sind für Docker-Workloads wie diesen zu schwach</li>



<li>Mindestens&nbsp;<strong>4 GB RAM</strong>&nbsp;auf der NAS (8 GB empfohlen, wenn n8n parallel läuft)</li>



<li>DSM 7.0 oder neuer</li>



<li>Fritz!Box mit aktiver Festnetznummer (getestet mit Fritz!Box 7590)<br><strong>Software &amp; Dienste:</strong></li>



<li>Docker bzw. Container Manager auf der Synology bereits eingerichtet</li>



<li>n8n läuft bereits als Docker-Container</li>



<li>OpenAI-Account mit hinterlegter Zahlungsmethode und API-Key</li>



<li>Optional: Cloudflare-Tunnel für externen Zugriff auf n8n-Webhooks<br><strong>Kenntnisse:</strong></li>



<li>SSH-Grundkenntnisse – also: Befehle in die Konsole tippen können</li>



<li>Grundlegendes Verständnis von Docker und compose.yaml</li>



<li>Keine Programmierkenntnisse nötig – du bearbeitest vorhandene Konfigurationsdateien</li>
</ul>



<h3 class="wp-block-heading">1.5 Kosten</h3>



<p><strong>Ulf</strong>: „Was kostet das Ganze?<br><strong>Bernd</strong>: &#8222;Ich hab schon ein ChatGPT-Plus-Abo &#8211; zählt das?&#8220;<br><strong>Tanja</strong>: „Leider nein, das Plus-Abo ist für die Chat-Oberfläche. Die Realtime API läuft über die Entwicklerplattform. Die hat eine eigene Abrechnung. Kein Abo, kein Monatspreis. Du zahlst minutengenau, genau das was du verbrauchst.&#8220;</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Modell</th><th>Kosten pro Minute (ca.)</th></tr></thead><tbody><tr><td>gpt-4o-realtime-preview</td><td>~$0,12–0,24</td></tr></tbody></table></figure>



<p><strong>Tanja</strong>: „Ein typisches Gespräch dauert ein bis drei Minuten. Das sind $0,12 bis $0,75 pro Anruf. Mit $10 Startguthaben kommst du für viele Wochen aus, wenn du das für gelegentliche Heimanrufe nutzt.&#8220;<br><strong>Ulf</strong>: „Und wenn das Guthaben aufgebraucht ist?&#8220;.<br><strong>Tanja</strong>: „Dann läuft nichts mehr. Deswegen setzt du in der OpenAI-Konsole einen&nbsp;<strong>Spending Alert</strong>&nbsp;und ein monatliches&nbsp;<strong>Kostenlimit</strong>&nbsp;– dann wirst du rechtzeitig benachrichtigt, bevor das Konto leer ist.&#8220;<br><strong>Bernd</strong>: „Ich würde das Limit einfach weglassen. Kostet ja nicht viel.&#8220;<br><strong>Tanja</strong>: „Wenn jemand deinen Webhook automatisiert aufruft, absichtlich oder aus Versehen, hast du am Monatsende eine unschöne Überraschung. Das Limit ist keine Bremse, es ist eine Sicherung.&#8220;</p>



<h3 class="wp-block-heading">1.6 Ablauf im Überblick</h3>



<p>Bevor wir bauen, die Vogelperspektive: So läuft ein kompletter Anruf durch das System.</p>



<ol class="wp-block-list">
<li>Anruf kommt auf der Fritz!Box-Festnetznummer an</li>



<li>Fritz!Box leitet den Anruf per SIP an Asterisk weiter</li>



<li>Asterisk nimmt den Anruf an und übergibt ihn an das Node.js-Relay (via ARI)</li>



<li>Das Relay öffnet eine WebSocket-Verbindung zu&nbsp;<code>wss://api.openai.com/v1/realtime</code>&nbsp;und streamt Audio bidirektional</li>



<li>OpenAI führt das komplette Gespräch mit dem Anrufer</li>



<li>Nach Gesprächsende sendet das Relay das Transkript per HTTP POST an n8n</li>



<li>n8n erstellt eine formatierte E-Mail mit Anrufernummer, Name, Anliegen, Dringlichkeit und vollständigem Gesprächsverlauf</li>
</ol>



<h2 class="wp-block-heading">2 Implementierung</h2>



<h3 class="wp-block-heading">2.1 Vorbereitung: OpenAI API-Key erzeugen</h3>



<p><strong>Ulf</strong>: „Wo bekomme ich diesen API-Key her? Ist das irgendwo in meinen Account-Einstellungen?&#8220;<br><strong>Tanja</strong>: „Fast. Du brauchst die&nbsp;<strong>Entwicklerplattform</strong>. Das ist eine separate Seite von OpenAI.&nbsp;<code>platform.openai.com</code>, nicht&nbsp;<code>chat.openai.com</code>.&#8220; Tanja tippt die Adresse. „Dort erstellst du den Key und lädst Guthaben auf.&#8220;<br><strong>Ulf</strong>: „Und das ist dann mit meinem normalen Account verknüpft?&#8220;<br><strong>Tanja</strong>: „Selbe E-Mail, aber separate Abrechnung. Was du dort verbrauchst, wird unabhängig von allem anderen abgerechnet.&#8220;</p>



<p>Die OpenAI Realtime API ist das KI-Gehirn deines Telefonassistenten. Sie ermöglicht Echtzeit-Sprachkonversationen: Spracherkennung, Antwortgenerierung und Text-to-Speech laufen in einem einzigen Modell mit sehr niedriger Latenz. Ohne API-Key läuft gar nichts.</p>



<p>Den Key bekommst du unter&nbsp;<a href="https://platform.openai.com/account/api-keys" target="_blank" rel="noopener">platform.openai.com/account/api-keys</a>. Wichtig: Das ist die Entwicklerplattform – ein vorhandenes ChatGPT-Abo hilft hier nicht weiter.</p>



<ol class="wp-block-list">
<li>In deinem Projekt:&nbsp;<strong>API Keys</strong>&nbsp;→&nbsp;<strong>Create new secret key</strong></li>



<li>Benenne den Key sinnvoll, z. B.&nbsp;<code>KI-Telefonassistent</code></li>



<li>Kopiere den Key&nbsp;<strong>sofort</strong>&nbsp;und speichere ihn im Passwortmanager – Keys werden nur einmal vollständig angezeigt</li>



<li>Gehe zu&nbsp;<strong>Billing</strong>&nbsp;→&nbsp;<strong>Add payment method</strong></li>



<li>Lade ein Startguthaben auf (z. B. $10 für erste Tests)</li>
</ol>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440083d125&quot;}" data-wp-interactive="core/image" data-wp-key="69e440083d125" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="683" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-1-OpenAI-Platform-API-Keys-Create-new-secret-key-1024x683.png" alt="BILD 1 - OpenAI Platform - API Keys - Create new secret key" class="wp-image-863" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-1-OpenAI-Platform-API-Keys-Create-new-secret-key-1024x683.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-1-OpenAI-Platform-API-Keys-Create-new-secret-key-300x200.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-1-OpenAI-Platform-API-Keys-Create-new-secret-key-768x512.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-1-OpenAI-Platform-API-Keys-Create-new-secret-key.png 1536w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 1 &#8211; OpenAI Platform &#8211; API Keys &#8211; Create new secret key</figcaption></figure>



<h3 class="wp-block-heading">2.2 Vorbereitung: IP-Telefon in der Fritz!Box einrichten</h3>



<p>Damit Asterisk Anrufe von der Fritz!Box empfangen kann, muss er sich dort wie ein normales Telefon anmelden. Wir richten dafür ein&nbsp;<strong>virtuelles IP-Telefon</strong>&nbsp;ein – die Fritz!Box behandelt es genauso wie ein echtes Schnurlostelefon, leitet Anrufe dorthin weiter und übergibt sie per SIP-Protokoll.</p>



<p><strong>Ulf</strong>: „Warum ein virtuelles Telefon?&#8220; Kann Asterisk sich nicht einfach direkt einklinken?&#8220;<br><strong>Tanja</strong>: „Stell dir vor, du willst in ein Bürogebäude rein. Du brauchst einen Ausweis. Das virtuelle IP-Telefon ist der Ausweis von Asterisk bei der Fritz!Box.&#8220;</p>



<ol class="wp-block-list">
<li>Melde dich an der Benutzeroberfläche deiner&nbsp;<strong>Fritz!Box 7590</strong>&nbsp;an (meist<code>http://fritz.box</code>)</li>



<li>Navigiere zu&nbsp;<strong>Telefonie</strong>&nbsp;-&gt;&nbsp;<strong>Telefoniegeräte</strong></li>



<li>Klicke auf&nbsp;<strong>Neues Gerät einrichten</strong></li>



<li>Wähle&nbsp;<strong>Telefon (mit oder ohne Anrufbeantworter)</strong>&nbsp;aus und klicke auf &#8222;Weiter&#8220;</li>



<li>Wähle&nbsp;<strong>LAN/WLAN (IP-Telefon)</strong>&nbsp;aus und gib dem Kind einen Namen (z. B.&nbsp;<code>Asterisk_KI</code>)</li>
</ol>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440083d837&quot;}" data-wp-interactive="core/image" data-wp-key="69e440083d837" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="694" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-2-Auswahl-LANWLAN-IP-Telefon-an-der-FritzBox-1024x694.png" alt="BILD 2 - Auswahl LAN/WLAN - IP-Telefon an der Fritz!Box" class="wp-image-865" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-2-Auswahl-LANWLAN-IP-Telefon-an-der-FritzBox-1024x694.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-2-Auswahl-LANWLAN-IP-Telefon-an-der-FritzBox-300x203.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-2-Auswahl-LANWLAN-IP-Telefon-an-der-FritzBox-768x521.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-2-Auswahl-LANWLAN-IP-Telefon-an-der-FritzBox.png 1395w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 2 &#8211; Auswahl LAN/WLAN &#8211; IP-Telefon an der Fritz!Box</figcaption></figure>



<ol start="6" class="wp-block-list">
<li><strong>WICHTIG (Zugangsdaten):</strong>&nbsp;Im nächsten Schritt vergibst du einen Benutzernamen und ein Passwort. Notiere dir diese Daten gut!
<ul class="wp-block-list">
<li><strong>Benutzername:</strong>&nbsp;<code>KI_ASSISTANT_USER</code>&nbsp;(muss mindestens 8 Zeichen haben)</li>



<li><strong>Passwort:</strong>&nbsp;`DEIN_SICHERES_PASSWORT</li>



<li><strong>Registrar</strong>&nbsp;(SIP-Server):&nbsp;<code>fritz.box</code>&nbsp;oder deine Fritz!Box-IP</li>
</ul>
</li>
</ol>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440083dea7&quot;}" data-wp-interactive="core/image" data-wp-key="69e440083dea7" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="693" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-3-Passwort-fuer-IP-Telefon-an-der-FritzBox-1024x693.png" alt="BILD 3 - Passwort für IP-Telefon an der Fritz!Box" class="wp-image-866" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-3-Passwort-fuer-IP-Telefon-an-der-FritzBox-1024x693.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-3-Passwort-fuer-IP-Telefon-an-der-FritzBox-300x203.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-3-Passwort-fuer-IP-Telefon-an-der-FritzBox-768x520.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-3-Passwort-fuer-IP-Telefon-an-der-FritzBox.png 1393w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 3 &#8211; Passwort für IP-Telefon an der Fritz!Box</figcaption></figure>



<ol start="7" class="wp-block-list">
<li>Wähle die&nbsp;<strong>Rufnummer</strong>&nbsp;aus, auf die der KI-Assistent reagieren soll – deine Festnetznummer</li>



<li>Bestätige die Einrichtung (ggf. musst du dies per Telefon-Code oder Tastendruck an der Fritz!Box verifizieren).</li>
</ol>



<h3 class="wp-block-heading">2.3 Vorbereitung: Synology NAS</h3>



<p><strong>Tanja</strong>: „Bevor wir Container bauen, legen wir die Ordnerstruktur an. Das ist wie der Werkzeugschrank, bevor man anfängt zu schrauben. Wer den überspringt, sucht hinterher alles.&#8220;<br><strong>Bernd</strong> hebt die Hand: „Ich fange immer direkt an. Hab keine Zeit für Vorbereitung.&#8220;<br><strong>Tanja</strong>:„Du hast letzte Woche zwei Stunden gesucht, wo du die compose.yaml hingelegt hast.&#8220;<br>Bernd schweigt.</p>



<p>Wir legen jetzt die Ordnerstruktur und die&nbsp;<code>.env</code>-Datei an, die später alle API-Keys und Zugangsdaten sicher aufbewahrt.</p>



<ol class="wp-block-list">
<li>Erstelle folgende Verzeichnisse auf der NAS:
<ul class="wp-block-list">
<li><code>/volume1/docker/asterisk/</code>
<ul class="wp-block-list">
<li><code>config/</code>&nbsp;– hier kommen später alle SIP- und Dialplan-Dateien rein</li>



<li><code>logs/</code>&nbsp;– damit wir sehen, was beim Telefonieren passiert</li>
</ul>
</li>
</ul>
</li>



<li>Erstelle darin die Datei&nbsp;<code>/volume1/docker/asterisk/.env</code></li>



<li>Öffne auf deinem PC einen Texteditor (TextEdit, VS Code oder Notepad++) und füge folgenden Inhalt ein:</li>
</ol>



<pre class="wp-block-code"><code># OpenAI
OPENAI_API_KEY=DEIN_OPENAI_API_KEY

# Wird später gebraucht:
OPENAI_REALTIME_MODEL=gpt-realtime
N8N_WEBHOOK_BASE_URL=https://n8n.DEINE_DOMAIN.de</code></pre>



<ol start="4" class="wp-block-list">
<li><strong>Berechtigungen setzen:</strong>&nbsp;Rechtsklick auf den&nbsp;<code>asterisk</code>-Ordner -&gt;&nbsp;<strong>Eigenschaften</strong>&nbsp;-&gt;&nbsp;<strong>Berechtigungen</strong>&nbsp;-&gt; Nur dein Admin-User soll lesenden Zugriff haben.</li>
</ol>



<p>Warum&nbsp;<code>.env</code>? Weil du damit in der&nbsp;<code>compose.yaml</code>&nbsp;sauber auf die Zugangsdaten referenzieren kannst, ohne sie direkt in YAML-Dateien oder Screenshots sichtbar zu machen. Das ist Best Practice – nicht Paranoia.</p>



<h3 class="wp-block-heading">2.4 Das richtige Modell wählen – Qualität vs. Kosten</h3>



<p>Aktuell stehen drei Realtime-Modelle zur Verfügung:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Modell</th><th>Status</th><th>Audio Input / 1M Token</th><th>Audio Output / 1M Token</th><th>ca. Kosten pro Anruf (3 min)</th></tr></thead><tbody><tr><td><code>gpt-realtime</code></td><td>GA – produktionsreif</td><td>$32</td><td>$64</td><td>~$0,12</td></tr><tr><td><code>gpt-realtime-mini</code></td><td>GA – kostengünstig</td><td>$10</td><td>$20</td><td>~$0,04</td></tr><tr><td><code>gpt-4o-realtime-preview</code></td><td>Preview – Vorgänger</td><td>$40</td><td>$80</td><td>~$0,15</td></tr></tbody></table></figure>



<p>Die Kosten pro Anruf sind Schätzwerte bei ca. 2 Minuten Nutzer-Audio und 1 Minute KI-Antwort. Längere Gespräche oder ausführliche System-Prompts erhöhen den Preis entsprechend.</p>



<p>Für dieses Projekt empfehle ich&nbsp;<code>gpt-realtime</code>. Es ist das erste allgemein verfügbare Realtime-Modell, wurde speziell für produktive Sprachagenten optimiert und bietet gegenüber&nbsp;<code>gpt-4o-realtime-preview</code>&nbsp;spürbar bessere Sprachqualität, zuverlässigeres Instruction Following – und liegt dabei 20 % günstiger. Besonders praktisch:&nbsp;<code>gpt-realtime</code>&nbsp;unterstützt neben WebRTC und WebSocket auch&nbsp;<strong>native SIP-Verbindungen</strong>&nbsp;– also genau das Protokoll, das Asterisk und die Fritz!Box sprechen.<br>Wer Kosten sparen möchte und keine hochkomplexen Gespräche erwartet, kann&nbsp;<code>gpt-realtime-mini</code>&nbsp;ausprobieren. Bei gelegentlichen Heimanrufen ist der Qualitätsunterschied im Alltag kaum spürbar – und die Kosten pro Anruf sinken auf einen Bruchteil.</p>



<h2 class="wp-block-heading">3 Asterisk als Docker-Container einrichten und mit der Fritz!Box verbinden</h2>



<p><strong>Ulf</strong>: „Also jetzt bauen wir Asterisk?&#8220;<br><strong>Tanja</strong>: „Jetzt bauen wir Asterisk. Aber wir machen es in zwei Schritten. Erst konfigurieren, dann starten, dann testen. Erst wenn der Test grünes Licht gibt, machen wir weiter.&#8220;<br><strong>Bernd</strong>: „Ich würde alles auf einmal starten. Spart Zeit.&#8220;<br><strong>Tanja</strong>: „Und wenn dann was nicht funktioniert, weißt du nicht wo.&#8220;<br><strong>Bernd</strong>: „Stimmt, ist mir schon passiert.&#8220;</p>



<p>Asterisk läuft als Docker-Container auf deiner Synology. Er übernimmt eine zentrale Rolle: Er registriert sich bei der Fritz!Box wie ein IP-Telefon, nimmt eingehende Anrufe entgegen und reicht sie an die OpenAI-Brücke weiter. Alles Folgende baut auf dieser Verbindung auf – deshalb testen wir sie explizit, bevor wir weitermachen.</p>



<h3 class="wp-block-heading">3.1 Docker-Setup: Die compose.yaml</h3>



<p>Die&nbsp;<code>compose.yaml</code>&nbsp;ist dein Bauplan. Anstatt kryptische Befehle in die Konsole zu tippen, definierst du hier einmalig, welche Dateien in den Container gemountet werden und wie er sich verhalten soll.</p>



<ol class="wp-block-list">
<li>Öffne einen Texteditor (z.B. TextEDIT, VS Code oder Notepad++) und erstelle eine neue Datei namens&nbsp;<code>compose.yaml</code></li>



<li>Kopiere den folgenden Block hinein:</li>
</ol>



<p><strong>Hinweis:</strong>&nbsp;In meinem Fall läuft n8n bereits, daher fügen wir hier nur den Asterisk-Teil hinzu. Wie man n8n installiert siehe <a href="https://www.foundic.org/n8n-selbst-hosten-synology-nas-docker-installation">https://www.foundic.org/n8n-selbst-hosten-synology-nas-docker-installation</a></p>



<pre class="wp-block-code"><code>version: "3.8"

services:
  asterisk:
    image: andrius/asterisk:20
    container_name: asterisk_ki
    restart: unless-stopped
    network_mode: "host"
    healthcheck:
      disable: true
    volumes:
      # === Config-Dateien (read-only) ===
      - /volume1/docker/asterisk/config/pjsip.conf:/etc/asterisk/pjsip.conf:ro
      - /volume1/docker/asterisk/config/extensions.conf:/etc/asterisk/extensions.conf:ro
      - /volume1/docker/asterisk/config/modules.conf:/etc/asterisk/modules.conf:ro
      - /volume1/docker/asterisk/config/logger.conf:/etc/asterisk/logger.conf:ro
      - /volume1/docker/asterisk/config/rtp.conf:/etc/asterisk/rtp.conf:ro
      - /volume1/docker/asterisk/config/ari.conf:/etc/asterisk/ari.conf:ro
      - /volume1/docker/asterisk/config/http.conf:/etc/asterisk/http.conf:ro
      # === Logs (read-write) ===
      - /volume1/docker/asterisk/logs:/var/log/asterisk:rw
    environment:
      - TZ=Europe/Berlin
      - ASTERISK_UID=0
      - ASTERISK_GID=0</code></pre>



<ol start="3" class="wp-block-list">
<li>Kopiere die fertige Datei nach&nbsp;<code>/volume1/docker/asterisk/</code></li>
</ol>



<p><strong>Warum&nbsp;<code>network_mode: "host"</code>?</strong><br><strong>Ulf</strong> zeigt auf die compose.yaml :„Moment, was bedeutet das hier <code>network_mode: host</code>? Klingt irgendwie gefährlich.&#8220;<br><strong>Tanja</strong>: „Ist es nicht, aber die Erklärung braucht eine Minute.&#8220;<br><strong>Bernd</strong>: „Ich kenn das, NAT. Hab ich mal bei uns im Büro eingerichtet. Hat nicht funktioniert.&#8220;<br><strong>Tanja</strong>: „Genau das ist das Problem. Stell dir vor, der Docker-Container ist ein Mitarbeiter, der in einem abgeschlossenen Glaskasten sitzt. Er kann nach draußen telefonieren, aber wenn jemand zurückruft, landet der Anruf an der Glaskasten-Tür, und der Container hört nichts. Das nennt sich One-Way-Audio: du hörst die andere Seite, aber sie hört dich nicht. Oder umgekehrt.&#8220;<br><strong>Ulf</strong>: „Das klingt wie beim Fußball wenn das Headset des Torwarts kaputt ist. Der Trainer brüllt, aber der Keeper hört nix.&#8220;<br><strong>Tanja</strong>: „Perfekter Vergleich. Mit&nbsp;<code>network_mode: host</code>&nbsp;reißen wir den Glaskasten weg. Der Container verhält sich dann so, als wäre er direkt die DiskStation – gleiche IP, gleiche Ports, kein NAT dazwischen. Asterisk und die Fritz!Box können sich problemlos gegenseitig hören.&#8220;<br><strong>Ulf</strong>: „Und das ist sicher?&#8220;<br><strong>Tanja</strong>: „Für diesen Anwendungsfall: ja. Asterisk lauscht nur auf den Ports, die wir ihm erlauben. Der Kompromiss ist bewusst eingegangen.&#8220;<br><strong>Bernd</strong> nickt langsam. „Ich hätte einfach alle Ports geöffnet.&#8220;<br><strong>Tanja</strong>: „Das, wäre nicht sicher.&#8220;</p>



<p><strong>Wichtig: Port 5060 muss frei sein.</strong>&nbsp;Mit&nbsp;<code>network_mode: "host"</code>&nbsp;kann Asterisk nur dann sauber SIP sprechen, wenn auf der DiskStation niemand sonst bereits auf Port 5060 (UDP/TCP) lauscht. Wenn der Port belegt ist, startet Asterisk zwar – aber die SIP-Registrierung schlägt still fehl, oder Calls brechen unerwartet ab.</p>



<p>Den RTP-Portbereich definieren wir nicht in der compose.yaml, sondern in der&nbsp;<code>rtp.conf</code>&nbsp;– das ist der richtige Ort dafür.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440083ea2e&quot;}" data-wp-interactive="core/image" data-wp-key="69e440083ea2e" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="539" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-4-Angelegte-Config-Ordner-auf-der-Diskstation-im-Asterisk-config-Verzeichnis-1024x539.png" alt="BILD 4 - Angelegte Config-Ordner auf der Diskstation im Asterisk Verzeichnis" class="wp-image-868" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-4-Angelegte-Config-Ordner-auf-der-Diskstation-im-Asterisk-config-Verzeichnis-1024x539.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-4-Angelegte-Config-Ordner-auf-der-Diskstation-im-Asterisk-config-Verzeichnis-300x158.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-4-Angelegte-Config-Ordner-auf-der-Diskstation-im-Asterisk-config-Verzeichnis-768x405.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-4-Angelegte-Config-Ordner-auf-der-Diskstation-im-Asterisk-config-Verzeichnis.png 1194w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 4 &#8211; Angelegte Config-Ordner auf der Diskstation im Asterisk Verzeichnis</figcaption></figure>



<h3 class="wp-block-heading">3.2 Docker-Setup: Asterisk-Container-Konfiguration</h3>



<p><strong>Ulf</strong>: „Sechs Dateien? Für einen Telefonserver?&#8220;<br><strong>Tanja</strong>: „Jede macht genau eine Sache. Stell dir vor, du richtest eine neue Werkstatt ein. Du hast einen Schrank für Werkzeuge, einen für Schrauben, einen für die Bedienungsanleitungen. Du könntest alles in eine einzige Schublade werfen.&#8220;<br><strong>Bernd</strong>: „Mach ich so&#8220;<br><strong>Ulf</strong>: „… aber dann weißt du hinterher nicht mehr, wo was ist, wenn etwas nicht funktioniert.&#8220; <strong>Tanja</strong> zählt an den Fingern ab: „<code>pjsip.conf</code>: wie Asterisk mit der Fritz!Box redet.&nbsp;<code>rtp.conf</code>: welche Ports für Audio reserviert sind.&nbsp;<code>extensions.conf</code>: was bei einem eingehenden Anruf passiert.&nbsp;<code>modules.conf</code>: welche Asterisk-Funktionen geladen werden.&nbsp;<code>logger.conf</code>: was ins Log geschrieben wird.&nbsp;<code>asterisk.conf</code>: globale Grundeinstellungen.&#8220;<br><strong>Ulf</strong>: „Also sechs Schubladen, jede beschriftet&#8220;,<br><strong>Tanja</strong>: „Genau. Wenn später Audio nicht funktioniert, schaust du in&nbsp;<code>rtp.conf</code>. Wenn Asterisk sich nicht bei der Fritz!Box registriert, schaust du in&nbsp;<code>pjsip.conf</code>. Du musst nicht eine riesige Datei durchsuchen, sondern weißt sofort wo das Problem liegt.&#8220;<br><strong>Bernd</strong>: „Ich hätte alles in eine Datei gepackt&#8220;.<br><strong>Tanja</strong>: „Das weiß ich. Fang einfach oben an. Eine Datei nach der anderen.&#8220;</p>



<p>Wir erstellen im Verzeichnis&nbsp;<code>/volume1/docker/asterisk/config/</code>&nbsp;diese sechs Dateien:</p>



<ol class="wp-block-list">
<li><code>pjsip.conf</code>&nbsp;→ SIP-Registrierung bei der Fritz!Box</li>



<li><code>rtp.conf</code>&nbsp;→ RTP-Portbereich (Real-time Transport Protocol für Audiodaten)</li>



<li><code>extensions.conf</code>&nbsp;→ Minimaler Dialplan (was passiert, wenn ein Anruf reinkommt)</li>



<li><code>modules.conf</code>&nbsp;→ welche Asterisk-Module geladen werden</li>



<li><code>logger.conf</code>&nbsp;→ welche Log-Nachrichten wo landen</li>



<li><code>asterisk.conf</code>&nbsp;→ globale Asterisk-Einstellungen</li>
</ol>



<h4 class="wp-block-heading">3.2.1 <code>pjsip.conf</code> &#8211; SIP zur Fritz!Box</h4>



<p>PJSIP ist der moderne SIP-Stack von Asterisk und wird von der Fritz!Box sauber unterstützt. Diese Datei definiert, wie Asterisk sich bei der Fritz!Box anmeldet und Anrufe entgegennimmt.<br><strong>Datei:</strong>&nbsp;<code>/volume1/docker/asterisk/config/pjsip.conf</code></p>



<pre class="wp-block-code"><code>&#91;global]
type=global
user_agent=Asterisk PBX

; ===== UDP TRANSPORT =====
&#91;transport-udp]
type=transport
protocol=udp
bind=0.0.0.0

; ===== FRITZBOX AUTHENTICATION =====
&#91;fritzbox-auth]
type=auth
auth_type=userpass
username=KI_FRITZBOX_USER
password=DEIN_SICHERES_FRITZBOX_PASSWORT

; ===== OUTBOUND REGISTRATION =====
&#91;fritzbox-reg]
type=registration
transport=transport-udp
outbound_auth=fritzbox-auth
server_uri=sip:fritz.box
client_uri=sip:KI_FRITZBOX_USER@fritz.box
retry_interval=60
expiration=3600

; ===== AOR (Address of Record) =====
&#91;fritzbox-aor]
type=aor
max_contacts=1
remove_existing=yes

; ===== IDENTIFY - Erkennt FritzBox =====
&#91;fritzbox-identify]
type=identify
endpoint=fritzbox
match=DEINE_FRITZBOX_IP

; ===== ENDPOINT (für ein- UND ausgehende Anrufe) =====
&#91;fritzbox]
type=endpoint
transport=transport-udp
context=from-fritzbox
aors=fritzbox-aor
auth=fritzbox-auth
outbound_auth=fritzbox-auth
disallow=all
allow=alaw
allow=ulaw
direct_media=no
force_rport=yes
rewrite_contact=yes
rtp_symmetric=yes
from_user=KI_FRITZBOX_USER
from_domain=fritz.box</code></pre>



<p><strong>Diese Platzhalter musst du ersetzen:</strong></p>



<ul class="wp-block-list">
<li><code>KI_FRITZBOX_USER</code>&nbsp;→ Benutzername aus der Fritz!Box (Schritt 2.2)</li>



<li><code>DEIN_SICHERES_FRITZBOX_PASSWORT</code>&nbsp;→ SIP-Passwort aus der Fritz!Box</li>



<li><code>DEINE_FRITZBOX_IP</code>&nbsp;→ z. B.&nbsp;<code>192.168.0.1</code></li>
</ul>



<h4 class="wp-block-heading">3.2.2 <code>rtp.conf</code> &#8211; Audio-Ports</h4>



<p>Wir legen den RTP-Portbereich explizit fest, damit Audio vorhersagbar läuft. RTP ist das Protokoll, das den eigentlichen Audiostrom überträgt – ohne definierten Portbereich könnte Asterisk beliebige Ports verwenden, was Firewalls und NAT noch chaotischer macht.<br><strong>Datei:</strong>&nbsp;<code>/volume1/docker/asterisk/config/rtp.conf</code></p>



<pre class="wp-block-code"><code>&#91;general]
rtpstart=20000
rtpend=20255</code></pre>



<p><strong>Firewall-Hinweis:</strong>&nbsp;Falls die Firewall auf der Diskstation aktiv ist, lege Regeln an für Port 5060 (UDP) und den Bereich 20000–20255 (UDP).</p>



<h4 class="wp-block-heading">3.2.3 <code>extensions.conf</code> &#8211; Minimal-Dialplan</h4>



<p><strong>Ulf</strong>: „Was macht der Dialplan?&#8220;<br><strong>Tanja</strong>: „Stell dir vor, Asterisk ist ein Empfangstresen. Der Dialplan ist die Arbeitsanweisung: Wenn jemand anruft, was passiert dann? Wohin wird der Anruf weitergeleitet?&#8220; Sie tippt kurz. „Im Moment sagen wir nur: Annehmen, kurz warten, an die OpenAI-Brücke übergeben.&#8220;<br><strong>Datei:</strong>&nbsp;<code>/volume1/docker/asterisk/config/extensions.conf</code></p>



<pre class="wp-block-code"><code>&#91;general]
static=yes
writeprotect=no

&#91;from-fritzbox]
; Eingehender Anruf von FritzBox → an OpenAI Relay weiterleiten
exten =&gt; s,1,NoOp(Eingehender Anruf von FritzBox - CID=${CALLERID(all)})
 same =&gt; n,Answer()
 same =&gt; n,Wait(0.5)
 same =&gt; n,NoOp(Uebergabe an OpenAI Realtime via Stasis...)
 same =&gt; n,Stasis(asterisk_to_openai_rt)
 same =&gt; n,Hangup()

; Catch-all für alle Nummern, die die FritzBox sendet
exten =&gt; _X.,1,Goto(from-fritzbox,s,1)</code></pre>



<p>Ein paar Erläuterungen für den Fall, dass du später debuggen musst:</p>



<ul class="wp-block-list">
<li><code>exten =&gt; _X.,1</code>&nbsp;fängt jede gerufene Nummer ab – die Fritz!Box übergibt oft konkrete MSN-Nummern, und so landest du sicher im Dialplan</li>



<li><code>NoOp(...)</code>&nbsp;schreibt ins Log, welche Nummer Asterisk tatsächlich sieht – hilft enorm beim Fehlersuchen</li>



<li><code>Wait(0.5)</code>&nbsp;entschärft bei manchen Setups Race-Conditions beim Audiostart</li>
</ul>



<h4 class="wp-block-heading">3.2.4 <code>modules.conf</code>, <code>logger.conf</code> und <code>asterisk.conf</code></h4>



<p>Diese drei Dateien sind der Maschinenkeller. Unspektakulär, aber ohne sie startet Asterisk nicht sauber.<br><strong>Datei:</strong>&nbsp;<code>/volume1/docker/asterisk/config/modules.conf</code></p>



<pre class="wp-block-code"><code>&#91;modules]
autoload=yes

; Sicherheitshalber kritische ARI-Module explizit laden
load = res_http_websocket.so
load = res_ari.so
load = res_ari_channels.so
load = res_ari_bridges.so
load = res_ari_events.so
load = res_stasis.so
load = res_stasis_answer.so
load = res_stasis_playback.so
load = res_stasis_recording.so
load = res_stasis_snoop.so
load = chan_rtp.so</code></pre>



<p>Asterisk hat hunderte Module.&nbsp;<code>autoload=yes</code>&nbsp;lädt alle automatisch – die kritischen ARI-Module werden zusätzlich explizit genannt, damit Asterisk sie auf jeden Fall findet.</p>



<p><strong>Datei:</strong>&nbsp;<code>/volume1/docker/asterisk/config/logger.conf</code></p>



<pre class="wp-block-code"><code>&#91;general]
dateformat=%F %T

&#91;logfiles]
console =&gt; notice,warning,error,verbose(5)
messages =&gt; notice,warning,error,verbose(5)</code></pre>



<p><strong>Datei:</strong>&nbsp;<code>/volume1/docker/asterisk/config/asterisk.conf</code></p>



<pre class="wp-block-code"><code>&#91;directories]
astetcdir =&gt; /etc/asterisk
astvarlibdir =&gt; /var/lib/asterisk
astdbdir =&gt; /var/lib/asterisk
astmoddir =&gt; /usr/lib/asterisk/modules
astspooldir =&gt; /var/spool/asterisk
astrundir =&gt; /var/run/asterisk
astlogdir =&gt; /var/log/asterisk

&#91;options]
verbose = 3
debug = 0</code></pre>



<p>Warum so minimal? Damit Asterisk sicher startet und wir die wichtigen Meldungen direkt auf der Konsole sehen. Datei-Logs können wir später gezielt ergänzen.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440083f5c2&quot;}" data-wp-interactive="core/image" data-wp-key="69e440083f5c2" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="491" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-5-Angelegte-Config-Ordner-auf-der-Diskstation-im-Asterisk-Verzeichnis-1024x491.png" alt="BILD 5 - Angelegte Config-Ordner auf der Diskstation im Asterisk - config Verzeichnis" class="wp-image-871" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-5-Angelegte-Config-Ordner-auf-der-Diskstation-im-Asterisk-Verzeichnis-1024x491.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-5-Angelegte-Config-Ordner-auf-der-Diskstation-im-Asterisk-Verzeichnis-300x144.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-5-Angelegte-Config-Ordner-auf-der-Diskstation-im-Asterisk-Verzeichnis-768x369.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-5-Angelegte-Config-Ordner-auf-der-Diskstation-im-Asterisk-Verzeichnis.png 1192w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 5 &#8211; Angelegte Config-Ordner auf der Diskstation im Asterisk &#8211; config Verzeichnis</figcaption></figure>



<h3 class="wp-block-heading">3.3 Asterisk im Docker starten</h3>



<p>Alle Dateien liegen an ihrem Platz. Jetzt starten wir den Container – über den Container Manager auf der Diskstation.</p>



<ol class="wp-block-list">
<li>Container Manager öffnen
<ul class="wp-block-list">
<li>DSM -&gt;&nbsp;<strong>Container Manager</strong></li>
</ul>
</li>



<li>Neues Projekt erstellen
<ul class="wp-block-list">
<li>Links:&nbsp;<strong>Projekt</strong></li>



<li><strong>Erstellen</strong></li>



<li>Projektname: <code>asterisk_ki</code></li>
</ul>
</li>



<li>compose.yml auswählen
<ul class="wp-block-list">
<li><strong>Von bestehender compose.yml</strong></li>



<li>Pfad auswählen: <code>/volume1/docker/asterisk/compose.yml</code></li>



<li>Weiter</li>
</ul>
</li>



<li>Projekt starten
<ul class="wp-block-list">
<li><strong>Erstellen &amp; starten</strong>&nbsp;(oder „Fertigstellen“ -&gt; „Starten“)</li>
</ul>
</li>
</ol>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440083ff2c&quot;}" data-wp-interactive="core/image" data-wp-key="69e440083ff2c" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="751" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-6-Container-Manager-Neues-Projekt-aus-compose.yml-erstellen-1024x751.png" alt="BILD 5 - Angelegte Config-Ordner auf der Diskstation im Asterisk - config Verzeichnis" class="wp-image-872" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-6-Container-Manager-Neues-Projekt-aus-compose.yml-erstellen-1024x751.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-6-Container-Manager-Neues-Projekt-aus-compose.yml-erstellen-300x220.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-6-Container-Manager-Neues-Projekt-aus-compose.yml-erstellen-768x563.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-6-Container-Manager-Neues-Projekt-aus-compose.yml-erstellen.png 1224w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 5 &#8211; Angelegte Config-Ordner auf der Diskstation im Asterisk &#8211; config Verzeichnis</figcaption></figure>



<p><strong>Firewall-Erinnerung:</strong>&nbsp;Falls die Firewall auf der Synology aktiv ist, jetzt Regeln anlegen: Port 5060 (UDP) und Port 20000–20255 (UDP).</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400840512&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400840512" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="827" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-7-Container-laeuft-und-Status-auf-gruen-Exit-Code-0-1024x827.png" alt="BILD 6 - Container Manager - Neues Projekt aus compose.yml erstellen" class="wp-image-873" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-7-Container-laeuft-und-Status-auf-gruen-Exit-Code-0-1024x827.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-7-Container-laeuft-und-Status-auf-gruen-Exit-Code-0-300x242.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-7-Container-laeuft-und-Status-auf-gruen-Exit-Code-0-768x620.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-7-Container-laeuft-und-Status-auf-gruen-Exit-Code-0.png 1202w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 6 &#8211; Container Manager &#8211; Neues Projekt aus compose.yml erstellen</figcaption></figure>



<h3 class="wp-block-heading">3.4 Prüfen, ob Asterisk bei der Fritz!Box registriert ist</h3>



<p><strong>Ulf</strong>: „Und jetzt einfach anrufen und schauen ob&#8217;s geht?&#8220;<br><strong>Tanja</strong>: „Nein, erst verifizieren wir, dass Asterisk sich registriert hat. Erst dann testen wir den Anruf. Wer diesen Schritt überspringt, verbringt anschließend eine Stunde damit, im Dunkeln zu tappen.&#8220;<br><strong>Bernd</strong>: „Ich hätte einfach angerufen&#8220;<br><strong>Tanja</strong>: „Das weiß ich.&#8220;</p>



<p>Wir schauen jetzt direkt in die Asterisk-Konsole. Dafür gibt es zwei Wege:<br><strong>Weg 1 – über den Container Manager:</strong></p>



<ul class="wp-block-list">
<li>Container Manager öffnen → Container&nbsp;<code>asterisk_ki</code>&nbsp;auswählen</li>



<li>Tab&nbsp;<strong>Terminal</strong>&nbsp;→&nbsp;<strong>Erstellen</strong>&nbsp;→&nbsp;<code>bash</code>&nbsp;wählen</li>



<li>Befehl eingeben:&nbsp;<code>asterisk -rvvv</code></li>



<li>Sobald der Prompt&nbsp;<code>asterisk*CLI&gt;</code>&nbsp;erscheint, eingeben:&nbsp;<code>pjsip show registrations</code><br><strong>Weg 2 – über SSH:</strong></li>



<li>SSH auf der Diskstation aktivieren: Systemsteuerung → Terminal &amp; SNMP → SSH-Dienst aktivieren</li>



<li>Terminal öffnen und einloggen:&nbsp;<code>ssh DEIN_DSM_USER@DEINE_DISKSTATION_IP</code></li>



<li>In die Asterisk-CLI:&nbsp;<code>docker exec -it asterisk_ki asterisk -rvvv</code></li>



<li>Registrierung anzeigen:&nbsp;<code>pjsip show registrations</code><br>Das Ergebnis sollte so aussehen:</li>
</ul>



<pre class="wp-block-code"><code>&lt;Registration/ServerURI..............................&gt;  &lt;Auth..........&gt;  &lt;Status.......&gt;
==========================================================================================
 fb-trunk/sip:192.168.178.1                              fb-auth           Registered</code></pre>



<p>Das Wort&nbsp;<strong>Registered</strong>&nbsp;ist dein grünes Licht. Alles andere –&nbsp;<code>Failed</code>,&nbsp;<code>Rejected</code>, gar keine Ausgabe – bedeutet: Zugangsdaten prüfen, Fritz!Box-Konfiguration nochmal kontrollieren, erst dann weitermachen.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400840c38&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400840c38" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="753" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-8-im-Terminal-unter-Asterisk-Registered-1024x753.png" alt="BILD 8 - im Terminal unter Asterisk - Registered" class="wp-image-874" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-8-im-Terminal-unter-Asterisk-Registered-1024x753.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-8-im-Terminal-unter-Asterisk-Registered-300x221.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-8-im-Terminal-unter-Asterisk-Registered-768x565.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-8-im-Terminal-unter-Asterisk-Registered.png 1223w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 8 &#8211; im Terminal unter Asterisk &#8211; Registered</figcaption></figure>



<h2 class="wp-block-heading">4 Die OpenAI-Brücke: WebSocket-Relay einrichten und KI-Gespräche aktivieren</h2>



<p><strong>Ulf</strong>: „Asterisk läuft, Fritz!Box meldet ‚Registered&#8216;, was kommt jetzt?&#8220;.<br><strong>Tanja</strong>: „Jetzt, bauen wir den spannendsten Teil. Das Relay. Der zweite Docker-Container, der Asterisk und OpenAI miteinander verbindet.&#8220;<br><strong>Bernd</strong>:„Ich würde das alles in einem Container zusammenstecken&#8220;.<br><strong>Tanja</strong>: „Dann hast du einen Container, der alles macht und bei dem du nichts mehr einzeln debuggen kannst. Zwei Container, zwei Verantwortlichkeiten – das ist sauberer.&#8220;<br><strong>Bernd</strong>: „Klingt nach mehr Arbeit.&#8220;<br><strong>Tanja</strong>: „Klingt nach weniger Kopfschmerzen.&#8220;</p>



<p>Das Relay übersetzt zwei grundlegend verschiedene Welten: auf der einen Seite das klassische RTP-Audioprotokoll von Asterisk, auf der anderen den WebSocket-Stream, den OpenAI erwartet. Sobald diese Brücke steht, übernimmt OpenAI das komplette Gespräch – Spracherkennung, Antwortgenerierung und Text-to-Speech in Echtzeit.</p>



<h3 class="wp-block-heading">4.1 Asterisk-to-OpenAI-Realtime (WebSocket Bridge)</h3>



<p>Wir erweitern die Ordnerstruktur um den openai-relay-Container:</p>



<pre class="wp-block-code"><code>/volume2/docker/
├── asterisk/
│   ├── compose.yaml
│   ├── config/
│   │   ├── pjsip.conf
│   │   ├── extensions.conf
│   │   ├── ari.conf
│   │   ├── http.conf
│   │   ├── modules.conf
│   │   ├── logger.conf
│   │   └── rtp.conf
│   └── logs/
└── openai-relay/
    ├── compose.yaml
    ├── Dockerfile
    └── config.conf</code></pre>



<p>Drei neue Dateien im Verzeichnis&nbsp;<code>openai-relay</code>: das&nbsp;<code>Dockerfile</code>, die&nbsp;<code>compose.yaml</code>&nbsp;und die&nbsp;<code>config.conf</code>. Schauen wir uns alle drei an.</p>



<h3 class="wp-block-heading">4.2 Das Dockerfile</h3>



<p>Das Dockerfile baut das Docker-Image direkt aus einem öffentlichen Repository – du musst keinen Code manuell klonen oder pflegen.<br>Erstelle die Datei&nbsp;<code>/volume1/docker/openai-relay/Dockerfile</code>:</p>



<pre class="wp-block-code"><code>FROM node:20-slim

RUN apt-get update &amp;&amp; apt-get install -y git &amp;&amp; rm -rf /var/lib/apt/lists/*

WORKDIR /app

# Community Edition klonen
RUN git clone https://github.com/infinitocloud/asterisk_to_openai_rt_community.git .

RUN npm install

ENV NODE_ENV=production

CMD &#91;"node", "index.js"]</code></pre>



<h3 class="wp-block-heading">4.3 Die&nbsp;<code>compose.yaml</code> für openai-relay</h3>



<p>Da Asterisk im&nbsp;<code>network_mode: host</code>&nbsp;läuft, muss das Relay dasselbe tun – sonst erreicht es die RTP-Audio-Ports nicht.<br>Erstelle die Datei&nbsp;<code>/volume1/docker/openai-relay/compose.yaml</code>:</p>



<pre class="wp-block-code"><code>version: "3.8"

services:
  openai-relay:
    build: .
    container_name: openai-relay
    restart: unless-stopped
    network_mode: "host"
    volumes:
      # config.conf wird in den Container gemountet
      - /volume1/docker/openai-relay/config.conf:/app/config.conf:ro
    environment:
      - TZ=Europe/Berlin
      - NODE_ENV=production
    depends_on: &#91;]
    # Hinweis: asterisk_ki muss ZUERST gestartet werden,
    # da openai-relay sich per ARI verbindet.
    # Da die Container in separaten compose-Dateien sind,
    # manuell sicherstellen: erst asterisk_ki, dann openai-relay.</code></pre>



<h3 class="wp-block-heading">4.4 Asterisk Core-Konfiguration: ari.conf und http.conf</h3>



<p><strong>Ulf</strong>: „Was ist ARI?&#8220;.<br><strong>Tanja</strong>: „ARI steht für Asterisk REST Interface. Es ist die Schnittstelle, über die das Node.js-Relay mit Asterisk kommuniziert. Ohne ARI kann das Relay keinen Anruf übernehmen.&#8220;<br><strong>Ulf</strong>: „Das klingt nach dem Trainertelefon zur Bank. Der Coach kann dem Ersatzspieler Anweisungen geben, ohne auf das Feld zu müssen.&#8220;<br><strong>Tanja</strong>: „Exakt&#8220;.</p>



<p>Diese beiden Dateien sind das Bindeglied zwischen Asterisk und dem Relay. Besonders wichtig:&nbsp;<code>type=user</code>&nbsp;in der&nbsp;<code>ari.conf</code>&nbsp;– das ist häufig der Grund, warum ARI-Verbindungen still scheitern.<br><strong>Datei:</strong>&nbsp;<code>/volume1/docker/asterisk/config/ari.conf</code></p>



<pre class="wp-block-code"><code>&#91;general]
enabled=yes
pretty=yes
allowed_origins=*

&#91;ari_user]
type=user
read_only=no
password=dein_ari_passwort</code></pre>



<p><strong>Diese Platzhalter musst du ersetzen:</strong></p>



<ul class="wp-block-list">
<li>ARI_USERNAME=ari_user -&gt; frei wählbarer Benutzername</li>



<li>ARI_PASSWORD=dein_ari_passwort -&gt; frei wählbares Passwort (merken, kommt gleich wieder)</li>
</ul>



<p><strong>Datei:</strong>&nbsp;<code>/volume1/docker/asterisk/config/http.conf</code></p>



<pre class="wp-block-code"><code>&#91;general]
enabled=yes
bindaddr=127.0.0.1
bindport=8088</code></pre>



<p><code>127.0.0.1</code>&nbsp;statt&nbsp;<code>0.0.0.0</code>: Da beide Container auf dem Host-Netz der Synology laufen, braucht der HTTP-Port nicht nach außen offen zu sein. Das ist eine einfache, effektive Sicherheitsmaßnahme.</p>



<h3 class="wp-block-heading">4.5 Das config.conf &#8211; Schaltzentrale des Relays</h3>



<p>Diese Datei ist das Herzstück des openai-relay-Containers. Hier trägst du ein, mit welchem OpenAI-Key das Relay spricht, wie es sich bei Asterisk anmeldet und was die KI beim Gespräch sagen soll.<br>Erstelle die Datei&nbsp;<code>/volume1/docker/openai-relay/config.conf</code>:</p>



<pre class="wp-block-code"><code># OpenAI Realtime API Key
OPENAI_API_KEY=OpenAI_Projekt_API_Key

# ARI Credentials (muessen mit ari.conf uebereinstimmen)
ARI_URL=http://127.0.0.1:8088
ARI_USERNAME=ari_user
ARI_PASSWORD=dein_ari_passwort

# Anruf Limit von 5 Minuten
CALL_DURATION_LIMIT_SECONDS=300

# System-Prompt fuer den Assistenten
SYSTEM_PROMPT=Du bist ein professioneller deutschsprachiger Telefonassistent. Fuehre das Gespraech in dieser Reihenfolge: 1) Begruesse den Anrufer freundlich und sage dass gerade niemand erreichbar ist und du die KI Telefon-Assistentin bist. 2) Frage nach dem Namen des Anrufers falls nicht bereits genannt. 3) Frage worum es geht und hoere aufmerksam zu. 4) Frage wie dringend das Anliegen ist. 5) Fasse das Anliegen kurz zusammen und bestaetige dass du die Nachricht weiterleiten wirst. 6) Verabschiede dich freundlich. Antworte immer auf Deutsch, kurz und praezise. Vermeide lange Monologe.

# Logging
LOG_LEVEL=info</code></pre>



<p><strong>Diese Platzhalter ersetzen:</strong></p>



<ul class="wp-block-list">
<li>OpenAI_Projekt_API_Key -&gt; dein OpenAI API-Key aus Schritt 2.1</li>



<li>ARI_USERNAME=ari_user -&gt; vdie Werte aus&nbsp;<code>ari.conf</code></li>



<li>ARI_PASSWORD=dein_ari_passwort -&gt; die Werte aus&nbsp;<code>ari.conf</code></li>
</ul>



<p>Den&nbsp;<code>SYSTEM_PROMPT</code>&nbsp;kannst du frei anpassen. Das ist die Persönlichkeit deines KI-Assistenten. Halte ihn konkret und strukturiert: Je klarer die Reihenfolge, desto zuverlässiger arbeitet das Modell.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400841692&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400841692" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="757" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-9-openai-relay-Docker-Image-direkt-aus-dem-Repository-gebaut-1024x757.png" alt="BILD 9 - openai-relay Docker-Image direkt aus dem Repository gebaut" class="wp-image-876" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-9-openai-relay-Docker-Image-direkt-aus-dem-Repository-gebaut-1024x757.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-9-openai-relay-Docker-Image-direkt-aus-dem-Repository-gebaut-300x222.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-9-openai-relay-Docker-Image-direkt-aus-dem-Repository-gebaut-768x568.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-9-openai-relay-Docker-Image-direkt-aus-dem-Repository-gebaut.png 1223w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 9 &#8211; openai-relay Docker-Image direkt aus dem Repository gebaut</figcaption></figure>



<h3 class="wp-block-heading">4.6 Stimme der KI ändern</h3>



<p>OpenAI bietet verschiedene Stimmen für die Realtime API an. Standard ist&nbsp;<code>alloy</code>&nbsp;– du kannst aber auf andere Stimmen wie&nbsp;<code>echo</code>,&nbsp;<code>fable</code>,&nbsp;<code>onyx</code>,&nbsp;<code>nova</code>&nbsp;oder&nbsp;<code>shimmer</code>&nbsp;wechseln.<br>Um die Stimme zu ändern, kopierst du zunächst die Konfigurationsdatei aus dem laufenden Container auf die NAS:</p>



<pre class="wp-block-code"><code>sudo docker cp openai-relay:/app/config.js /volume2/docker/openai-relay/config.js</code></pre>



<p>Füge in dieser&nbsp;<code>config.js</code>&nbsp;nach dem zweiten Eintrag folgende Zeile ein:</p>



<pre class="wp-block-code"><code>OPENAI_VOICE: process.env.OPENAI_VOICE || 'alloy',</code></pre>



<p>Damit der Container diese Datei auch findet, erweitere die&nbsp;<code>compose.yaml</code>&nbsp;um den zweiten Volume-Eintrag:</p>



<pre class="wp-block-code"><code>volumes:&amp;nbsp;
-&amp;nbsp;/volume2/docker/openai-relay/config.conf:/app/config.conf:ro&amp;nbsp;
-&amp;nbsp;/volume2/docker/openai-relay/config.js:/app/config.js:ro</code></pre>



<p>Und trage in der&nbsp;<code>config.conf</code>&nbsp;ein:</p>



<pre class="wp-block-code"><code>OPENAI_VOICE=alloy</code></pre>



<p>Danach den Container neu starten . Die neue Stimme ist aktiv.</p>



<h3 class="wp-block-heading">4.7 Webhook für n8n Workflow vorbereiten</h3>



<p>Aktuell werden Transkripte nur in die Konsole geloggt und gehen nach dem Auflegen verloren. Jetzt erweitern wir das System so, dass nach jedem Gespräch automatisch ein Transkript an n8n geschickt wird.</p>



<p><strong>Ulf</strong>: „Moment, wir müssen Code in fertigen Dateien ändern?&#8220;<br><strong>Tanja</strong>: „Wir kopieren die Dateien erst raus, ändern sie, und mounten sie dann als Volume in den Container rein. Der Container bleibt unberührt. Wir steuern sein Verhalten von außen.&#8220;<br><strong>Ulf</strong>: „Das ist wie beim Fußball&#8220;. Der Spieler ist unveränderlich, aber der Trainer gibt ihm von außen neue Anweisungen.&#8220;<br><strong>Tanja</strong>: „Genau.&#8220;</p>



<p>Schritt 1: Es müssen folgende JavaScript-Dateien aus dem Container kopiert werden, damit wir sie anpassen und als Volume mounten können.</p>



<pre class="wp-block-code"><code>sudo docker cp openai-relay:/app/config.js /volume1/docker/openai-relay/config.js
sudo docker cp openai-relay:/app/asterisk.js /volume1/docker/openai-relay/asterisk.js
sudo docker cp openai-relay:/app/openai.js /volume1/docker/openai-relay/openai.js</code></pre>



<p>Schritt 2: In&nbsp;<code>/volume1/docker/openai-relay/config.js</code>&nbsp;suche nach&nbsp;<code>INITIAL_MESSAGE:</code>&nbsp;und füge direkt darüber ein:</p>



<pre class="wp-block-code"><code>OPENAI_VOICE: process.env.OPENAI_VOICE || 'alloy',
N8N_WEBHOOK_URL: process.env.N8N_WEBHOOK_URL || '',
INITIAL_MESSAGE:&amp;nbsp;process.env.INITIAL_MESSAGE&amp;nbsp;||&amp;nbsp;'Hi',</code></pre>



<p>Schritt 3: config.conf ergänzen<br>Füge am Ende der&nbsp;<code>/volume1/docker/openai-relay/config.conf</code>&nbsp;hinzu:</p>



<pre class="wp-block-code"><code>OPENAI_VOICE=alloy&amp;nbsp;
N8N_WEBHOOK_URL=https://n8n.civicgem.org/webhook/NEUE_WEBHOOK_ID</code></pre>



<p><strong>Hinweis:</strong>&nbsp;Die&nbsp;<code>NEUE_WEBHOOK_ID</code>&nbsp;wird erst im nächsten Schritt beim Aufbau des n8n-Workflows definiert. Trag hier zunächst einen Platzhalter ein und ersetze ihn danach.</p>



<p>Schritt 4: compose.yaml aktualisieren<br>Erweitere die Volumes in&nbsp;<code>/volume1/docker/openai-relay/compose.yaml</code>:</p>



<pre class="wp-block-code"><code>volumes:
      - /volume2/docker/openai-relay/config.conf:/app/config.conf:ro
      - /volume2/docker/openai-relay/config.js:/app/config.js:ro
      - /volume2/docker/openai-relay/asterisk.js:/app/asterisk.js:ro
      - /volume2/docker/openai-relay/openai.js:/app/openai.js:ro</code></pre>



<p>Aktuell werden die Transkripte nur in die Konsole geloggt und gehen nach dem Anruf verloren. Wir müssen&nbsp;<code>openai.js</code>&nbsp;so erweitern, dass die Transkripte während des Gesprächs gesammelt und nach Gesprächsende per HTTP POST an n8n geschickt werden.</p>



<p>Schritt 5: openai.js erweitern – Transkript sammeln<br>Suche in&nbsp;<code>/volume1/docker/openai-relay/openai.js</code>&nbsp;die Zeile (ca. Zeile 88):</p>



<pre class="wp-block-code"><code>  let lastUserItemId = null;</code></pre>



<p>Füge&nbsp;<strong>direkt darunter</strong>&nbsp;ein:</p>



<pre class="wp-block-code"><code>  let transcriptLog = &#91;];</code></pre>



<p>Dann suche diesen Block (ca. Zeile 164-168):</p>



<pre class="wp-block-code"><code>if (role === 'User') {
              logOpenAI`User command transcription for ${channelId}: ${response.transcript}`, 'info');
            } else {
              logOpenAI(`Assistant transcription for ${channelId}: ${response.transcript}`, 'info');
            }</code></pre>



<p>Ersetze ihn durch:</p>



<pre class="wp-block-code"><code>            if (role === 'User') {
              logOpenAI(`User command transcription for ${channelId}: ${response.transcript}`, 'info');
              transcriptLog.push({ role: 'user', text: response.transcript, time: new Date().toISOString() });
            } else {
              logOpenAI(`Assistant transcription for ${channelId}: ${response.transcript}`, 'info');
              transcriptLog.push({ role: 'assistant', text: response.transcript, time: new Date().toISOString() });
            }</code></pre>



<p>Dann suche (ca. Zeile 167)</p>



<pre class="wp-block-code"><code>            logOpenAI`User command transcription for ${channelId}: ${response.transcript}`, 'info');
          }
          break;
        case 'response.audio.done':</code></pre>



<p>Ersetze die eine Zeile:</p>



<pre class="wp-block-code"><code>            logOpenAI(`User command transcription for ${channelId}: ${response.transcript}`, 'info');</code></pre>



<p>durch:</p>



<pre class="wp-block-code"><code>            logOpenAI(`User command transcription for ${channelId}: ${response.transcript}`, 'info');
            transcriptLog.push({ role: 'user', text: response.transcript, time: new Date().toISOString() });</code></pre>



<p>Zum Schluss: Suche&nbsp;<code>sipMap.set(channelId, channelData);</code>&nbsp;innerhalb von&nbsp;<code>connectWebSocket</code>&nbsp;(ca. Zeile 246) und füge&nbsp;<strong>direkt davor</strong>&nbsp;ein:</p>



<pre class="wp-block-code"><code>        channelData.transcriptLog = transcriptLog;</code></pre>



<p>Suche diesen Block (ca. Zeile 180):</p>



<pre class="wp-block-code"><code>        case 'conversation.item.input_audio_transcription.completed':
          if (response.transcript) {
            logger.debug(`User transcript completed - Full message: ${JSON.stringify(response, null, 2)}`);
            logOpenAI(`User command transcription for ${channelId}: ${response.transcript}`, 'info');
          }
          break;</code></pre>



<p>Ersetze durch:</p>



<pre class="wp-block-code"><code>        case 'conversation.item.input_audio_transcription.completed':
          if (response.transcript) {
            logger.debug(`User transcript completed - Full message: ${JSON.stringify(response, null, 2)}`);
            logOpenAI(`User command transcription for ${channelId}: ${response.transcript}`, 'info');
            transcriptLog.push({ role: 'user', text: response.transcript, time: new Date().toISOString() });
          }
          break;</code></pre>



<p>Suche Zeile (ca. Zeile 224):</p>



<pre class="wp-block-code"><code>            input_audio_transcription: {
              model: 'whisper-1',
              language: 'en'
            },</code></pre>



<p>Suche&nbsp;<code>language: en</code>&nbsp;und ersetze durch <code>de</code> für Deutsche Sprache</p>



<pre class="wp-block-code"><code>              language: 'de'</code></pre>



<p>Schritt 6: asterisk.js erweitern &#8211; Transkript an n8n senden<br>…/docker/openai-relay/asterisk.js<code>&amp;nbsp;erweitern**&amp;nbsp;— nach Gesprächsende die gesammelten Transkripte an n8n senden. </code></p>



<p>Änderung 1:&nbsp;Ganz oben nach der letzten&nbsp;<code>require</code>-Zeile einfügen:</p>



<pre class="wp-block-code"><code>const http = require('http');
const https = require('https');</code></pre>



<p>Änderung 2:&nbsp;Suche in der&nbsp;<code>cleanupChannel</code>-Funktion diese Zeile:</p>



<pre class="wp-block-code"><code>    }&amp;nbsp;catch&amp;nbsp;(e)&amp;nbsp;{&amp;nbsp;
      logger.error(`Cleanup error for&amp;nbsp;${channelId}:&amp;nbsp;${e.message}`);
    } finally {
      cleanupPromises.delete(channelId);
      cleanupPromises.delete(`ws_${channelId}`);
    }</code></pre>



<p>Füge&nbsp;<strong>direkt davor</strong>&nbsp;(also vor&nbsp;<code>} finally {</code>) ein:</p>



<pre class="wp-block-code"><code>      // Send transcript to n8n webhook
      if (config.N8N_WEBHOOK_URL &amp;&amp; channelData.transcriptLog &amp;&amp; channelData.transcriptLog.length &gt; 0) {
        try {
          const payload = JSON.stringify({
            channelId: channelId,
            callerName: channelData.channel?.caller?.name || 'Unbekannt',
            callerNumber: channelData.channel?.caller?.number || 'Unbekannt',
            callStart: channelData.transcriptLog&#91;0]?.time || new Date().toISOString(),
            callEnd: new Date().toISOString(),
            transcript: channelData.transcriptLog
          });
          const url = new URL(config.N8N_WEBHOOK_URL);
          const client = url.protocol === 'https:' ? https : http;
          const req = client.request(url, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload) }
          }, (res) =&gt; {
            logger.info(`n8n webhook response for ${channelId}: ${res.statusCode}`);
          });
          req.on('error', (e) =&gt; logger.error(`n8n webhook error for ${channelId}: ${e.message}`));
          req.write(payload);
          req.end();
          logger.info(`Transcript sent to n8n for ${channelId} (${channelData.transcriptLog.length} entries)`);
        } catch (e) {
          logger.error(`Failed to send transcript to n8n for ${channelId}: ${e.message}`);
        }
      }</code></pre>



<h3 class="wp-block-heading">4.8 Cloudfare öffenen für Webhooks</h3>



<p><strong>Ulf</strong>: „Ich nutze Cloudflare mit Zero Trust für n8n. Muss ich da was anpassen?&#8220;<br><strong>Tanja</strong>: „Ja, Zero Trust blockiert standardmäßig alle eingehenden Requests, die nicht authentifiziert sind – also auch Webhooks von OpenAI. Wir müssen einen Bypass für den Webhook-Pfad einrichten.&#8220;</p>



<p>Wenn du Cloudflare mit Zero Trust für n8n nutzt, werden Webhooks grundsätzlich geblockt. Wir richten eine Ausnahme speziell für den&nbsp;<code>/webhook/</code>-Pfad ein. Zur EInrichtung von Cloudflare siehe https://www.foundic.org/n8n-cloudflare-tunnel-synology-nas.</p>



<p>Teil 1 – Neue Access Application anlegen:</p>



<ol class="wp-block-list">
<li>Cloudflare Zero Trust Dashboard öffnen:
<ol class="wp-block-list">
<li>Gehe zu:&nbsp;<strong><a href="https://one.dash.cloudflare.com/" target="_blank" rel="noopener">https://one.dash.cloudflare.com/</a></strong></li>



<li>Melde dich an</li>



<li>Wähle dein Team/Account</li>
</ol>
</li>



<li>Access Application finden:
<ol class="wp-block-list">
<li>Navigiere zu:&nbsp;Protect &amp; Connect -&gt; Zero Trust -&gt; Access controls -&gt; Applications</li>



<li>Finde deine&nbsp;<strong>n8n-Application</strong>&nbsp;in der Liste</li>



<li>Wähle &#8222;+ Add an application&#8220;</li>



<li>Select: Self-hosted</li>



<li>Applciation name: n8n-webhook</li>



<li>Session Duration: 24hours</li>



<li><strong>&#8222;+ Add public hostname&#8220;</strong>
<ul class="wp-block-list">
<li>Subdomain: die bisher benutzte</li>



<li>Domain: deine Domain</li>



<li>Path: <strong><code>webhook/*</code></strong></li>
</ul>
</li>



<li>Wähle links im Menü&nbsp;<strong>&#8222;Policies&#8220;</strong> aus</li>



<li>Klicke auf&nbsp;<strong>&#8222;Add a policy&#8220;</strong>
<ul class="wp-block-list">
<li>Policy konfigurieren:<br><strong>Policy Name:</strong> <code>n8n Webhook Bypass</code><br>Action:&nbsp;<strong>&#8222;Bypass&#8220;</strong><br>Session duration: <code>Same as application session timeout</code><br><strong>Selection:</strong> Everyone<br>Klicke auf&nbsp;<strong>&#8222;Save&#8220;</strong>&nbsp;</li>
</ul>
</li>
</ol>
</li>
</ol>



<figure class="wp-block-image aligncenter size-large"><a href="https://www.foundic.org/?attachment_id=878"><img loading="lazy" decoding="async" width="1024" height="683" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-10-Cloudfare-Web-app-exploits-einrichten-Manage-custom-rules-1024x683.png" alt="BILD 10 - Cloudfare - Web app exploits einrichten - Manage custom rules" class="wp-image-878" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-10-Cloudfare-Web-app-exploits-einrichten-Manage-custom-rules-1024x683.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-10-Cloudfare-Web-app-exploits-einrichten-Manage-custom-rules-300x200.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-10-Cloudfare-Web-app-exploits-einrichten-Manage-custom-rules-768x512.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-10-Cloudfare-Web-app-exploits-einrichten-Manage-custom-rules.png 1536w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">BILD 10 &#8211; Cloudfare &#8211; Web app exploits einrichten &#8211; Manage custom rules</figcaption></figure>



<p>Teil 2 – WAF-Regel erstellen:<br>Gehe im Cloudflare Dashboard zur obersten Kontoebene -&gt; Domains -&gt; deine Domain -&gt; (links im Menü)&nbsp;<strong>Security</strong>&nbsp;-&gt;&nbsp;<strong>Overview</strong> -&gt; in der Mitte im Kasten „Web app exploits&#8220; -&gt;&nbsp;<strong>Manage custom rules</strong>&nbsp;-&gt;&nbsp;<strong>+ Create rule</strong>&nbsp;-&gt; <strong>Custom rules</strong></p>



<ul class="wp-block-list">
<li>Rule name: <code>Allow n8n Webhook</code></li>



<li>Field: <code>URI Path</code>&nbsp;…,&nbsp;Operator: <code>starts with</code>,&nbsp;Value: ..&nbsp;<code>/webhook/</code></li>



<li>Choose action: Skip</li>



<li>Aktiviere alle Sicherheitsoptionen (WAF, Super Bot Fight Mode etc.), damit OpenAI ungehindert durchkommt</li>



<li>Klicke auf&nbsp;<strong>Deploy</strong></li>
</ul>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400843873&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400843873" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="683" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-11-Cloudfare-Manage-custom-rules-eingerichtet-1024x683.png" alt="BILD 11 - Cloudfare - Manage custom rules - eingerichtet" class="wp-image-879" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-11-Cloudfare-Manage-custom-rules-eingerichtet-1024x683.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-11-Cloudfare-Manage-custom-rules-eingerichtet-300x200.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-11-Cloudfare-Manage-custom-rules-eingerichtet-768x512.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-11-Cloudfare-Manage-custom-rules-eingerichtet.png 1536w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 11 &#8211; Cloudfare &#8211; Manage custom rules &#8211; eingerichtet</figcaption></figure>



<h3 class="wp-block-heading">4.9 n8n Workflow bauen</h3>



<p><strong>Ulf</strong>: „Jetzt kommt der Teil, den ich kenne, n8n.&#8220;<br><strong>Tanja</strong>: „Fast, erst brauchen wir noch ein App-Passwort für Gmail. Das normale Google-Passwort geht nicht.&#8220;<br><strong>Ulf</strong>: „Warum nicht?&#8220;<br><strong>Tanja</strong>: „Weil Google beim normalen Passwort verlangt, dass du dich per Browser verifizierst. Eine Maschine kann das nicht. Ein App-Passwort ist ein separater 16-stelliger Code, der nur für automatisierte Zugänge gedacht ist.&#8220;<br><strong>Ulf</strong>: „Und wenn ich keins hab?&#8220;<br><strong>Tanja</strong>: „Dann bleibt die E-Mail aus.&#8220;</p>



<p>Schritt 1: Gmail App-Passwort erstellen<br>Falls der n8n Workflow eine Zusammenfassung an Gmail bzw. Googel Mail senden soll brauchst Du ein&nbsp;<strong>App-Passwort</strong>&nbsp;(nicht Dein normales Gmail-Passwort). So richtest Du es ein:<br><strong>Gmail App-Passwort erstellen:</strong></p>



<ul class="wp-block-list">
<li>Gehe zu&nbsp;<a href="https://myaccount.google.com/apppasswords" target="_blank" rel="noopener">https://myaccount.google.com/apppasswords</a></li>



<li>(2-Faktor-Authentifizierung muss aktiv sein)</li>



<li>App-Name:&nbsp;<code>n8n</code></li>



<li>Du bekommst ein 16-stelliges Passwort &#8211; kopiere es</li>
</ul>



<p>Schritt 2: SMTP Credentials in n8n anlegen<br><strong>SMTP Credentials anlegen</strong> in n8n anlegen</p>



<ul class="wp-block-list">
<li>n8n -&gt;&nbsp;<strong>Settings</strong>&nbsp;-&gt;&nbsp;<strong>Credentials</strong>&nbsp;-&gt;&nbsp;<strong>Add Credential</strong>&nbsp;-&gt; Typ:&nbsp;<strong>SMTP</strong></li>



<li>Name:&nbsp;<code>SMTP Gmail account</code></li>



<li>User:&nbsp;<code>deine-adresse@gmail.com</code></li>



<li>Password: dein 16-stelliges App-Passwort</li>



<li>Host:&nbsp;<code>smtp.gmail.com</code></li>



<li>Port:&nbsp;<code>465</code></li>



<li>SSL/TLS:&nbsp;<strong>Ein</strong></li>



<li>Speichern</li>
</ul>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440084400a&quot;}" data-wp-interactive="core/image" data-wp-key="69e440084400a" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="683" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-12-n8n-eMail-Credentials-anlegen-1024x683.png" alt="BILD 12 - n8n - eMail Credentials anlegen" class="wp-image-880" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-12-n8n-eMail-Credentials-anlegen-1024x683.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-12-n8n-eMail-Credentials-anlegen-300x200.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-12-n8n-eMail-Credentials-anlegen-768x512.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-12-n8n-eMail-Credentials-anlegen.png 1536w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 12 &#8211; n8n &#8211; eMail Credentials anlegen</figcaption></figure>



<p>Schritt 3: Die drei Workflow-Nodes<br>Erstelle einen neuen n8n-Workflow mit drei Nodes hintereinander.<br><strong>Node 1: Webhook</strong></p>



<ul class="wp-block-list">
<li>Method:&nbsp;<code>POST</code></li>



<li>Path:&nbsp;<code>anruf-zusammenfassung</code></li>



<li>Authentication:&nbsp;<code>None</code></li>
</ul>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400844631&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400844631" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="683" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-12-n8n-eMail-Credentials-anlegen-1-1024x683.png" alt="BILD 13 - n8n - Webhook Node erstellen" class="wp-image-881" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-12-n8n-eMail-Credentials-anlegen-1-1024x683.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-12-n8n-eMail-Credentials-anlegen-1-300x200.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-12-n8n-eMail-Credentials-anlegen-1-768x512.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-12-n8n-eMail-Credentials-anlegen-1.png 1536w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 13 &#8211; n8n &#8211; Webhook Node erstellen</figcaption></figure>



<p><strong>Node 2: Code in JavaScript</strong></p>



<ul class="wp-block-list">
<li>Mode:&nbsp;<code>Run Once for All Items</code></li>



<li>Language:&nbsp;<code>JavaScript</code></li>
</ul>



<pre class="wp-block-code"><code>// Transkript formatieren
const body = $input.first().json.body;
const transcript = body.transcript || &#91;];
const callerName = body.callerName || 'Unbekannt';
const callerNumber = body.callerNumber || 'Unbekannt';
const callStart = body.callStart ? new Date(body.callStart).toLocaleString('de-DE', { timeZone: 'Europe/Berlin' }) : 'Unbekannt';
const callEnd = body.callEnd ? new Date(body.callEnd).toLocaleString('de-DE', { timeZone: 'Europe/Berlin' }) : 'Unbekannt';

// Gespraechsverlauf als Text
let gespraech = '';
for (const entry of transcript) {
  const rolle = entry.role === 'assistant' ? 'Anna (KI)' : 'Anrufer';
  gespraech += `${rolle}: ${entry.text}\n\n`;
}

// Zusammenfassung erstellen
let zusammenfassung = `ANRUF-ZUSAMMENFASSUNG\n`;
zusammenfassung += `========================\n\n`;
zusammenfassung += `Anrufer: ${callerName}\n`;
zusammenfassung += `Telefonnummer: ${callerNumber}\n`;
zusammenfassung += `Anruf Beginn: ${callStart}\n`;
zusammenfassung += `Anruf Ende: ${callEnd}\n\n`;
zusammenfassung += `GESPRAECHSVERLAUF:\n`;
zusammenfassung += `------------------------\n\n`;
zusammenfassung += gespraech;

// HTML Version fuer E-Mail
let html = `&lt;h2&gt;Anruf-Zusammenfassung&lt;/h2&gt;`;
html += `&lt;table style="border-collapse:collapse; margin-bottom:20px;"&gt;`;
html += `&lt;tr&gt;&lt;td style="padding:4px 12px 4px 0; font-weight:bold;"&gt;Anrufer:&lt;/td&gt;&lt;td&gt;${callerName}&lt;/td&gt;&lt;/tr&gt;`;
html += `&lt;tr&gt;&lt;td style="padding:4px 12px 4px 0; font-weight:bold;"&gt;Telefonnummer:&lt;/td&gt;&lt;td&gt;${callerNumber}&lt;/td&gt;&lt;/tr&gt;`;
html += `&lt;tr&gt;&lt;td style="padding:4px 12px 4px 0; font-weight:bold;"&gt;Beginn:&lt;/td&gt;&lt;td&gt;${callStart}&lt;/td&gt;&lt;/tr&gt;`;
html += `&lt;tr&gt;&lt;td style="padding:4px 12px 4px 0; font-weight:bold;"&gt;Ende:&lt;/td&gt;&lt;td&gt;${callEnd}&lt;/td&gt;&lt;/tr&gt;`;
html += `&lt;/table&gt;`;
html += `&lt;h3&gt;Gespr\u00e4chsverlauf&lt;/h3&gt;`;
for (const entry of transcript) {
  const rolle = entry.role === 'assistant' ? 'Anna (KI)' : 'Anrufer';
  const color = entry.role === 'assistant' ? '#2563eb' : '#059669';
  html += `&lt;p&gt;&lt;strong style="color:${color};"&gt;${rolle}:&lt;/strong&gt; ${entry.text}&lt;/p&gt;`;
}

const subject = `Anruf von ${callerName} (${callerNumber}) - ${callStart}`;

return &#91;{ json: { subject, text: zusammenfassung, html, callerName, callerNumber } }];</code></pre>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400844c58&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400844c58" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="638" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-14-n8n-Code-in-JavaScript-1024x638.png" alt="BILD 14 - n8n - Code in JavaScript" class="wp-image-882" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-14-n8n-Code-in-JavaScript-1024x638.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-14-n8n-Code-in-JavaScript-300x187.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-14-n8n-Code-in-JavaScript-768x479.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-14-n8n-Code-in-JavaScript-1536x957.png 1536w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-14-n8n-Code-in-JavaScript.png 1577w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 14 &#8211; n8n &#8211; Code in JavaScript</figcaption></figure>



<p>Als letzten <strong>Node 3: Send Email</strong> erstellen</p>



<ul class="wp-block-list">
<li>Credential to connect with:&nbsp;<code>SMTP Gmail account</code></li>



<li>Operations:&nbsp;<code>Send</code></li>



<li>From Email: deine E-Mail-Adresse</li>



<li>To Email: deine E-Mail-Adresse</li>



<li>Subject:&nbsp;<code>{{ $json.subject }}</code></li>



<li>Email Format:&nbsp;<code>HTML</code></li>



<li>HTML:&nbsp;<code>{{ $json.html }}</code></li>
</ul>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e44008452d9&quot;}" data-wp-interactive="core/image" data-wp-key="69e44008452d9" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="683" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-15-n8n-E-Mail-senden-1024x683.png" alt="BILD 15 - n8n - E-Mail senden" class="wp-image-884" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-15-n8n-E-Mail-senden-1024x683.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-15-n8n-E-Mail-senden-300x200.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-15-n8n-E-Mail-senden-768x512.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-15-n8n-E-Mail-senden.png 1536w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 15 &#8211; n8n &#8211; E-Mail senden</figcaption></figure>



<p>Schritt 4: Workflow aktivieren<br>Aktiviere den Workflow über&nbsp;<strong>Publish</strong>&nbsp;und kopiere die Webhook-URL aus dem Webhook-Node. Sie sieht etwa so aus:</p>



<pre class="wp-block-code"><code>https:&#47;&#47;n8n.deine-domain.de/webhook/anruf-zusammenfassung</code></pre>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440084589d&quot;}" data-wp-interactive="core/image" data-wp-key="69e440084589d" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="639" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-16-n8n-Workflow-Uebersicht-1024x639.png" alt="BILD 16- n8n - Workflow Übersicht" class="wp-image-885" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-16-n8n-Workflow-Uebersicht-1024x639.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-16-n8n-Workflow-Uebersicht-300x187.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-16-n8n-Workflow-Uebersicht-768x479.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-16-n8n-Workflow-Uebersicht.png 1285w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 16- n8n &#8211; Workflow Übersicht</figcaption></figure>



<p>Schritt 5: URL in config.conf eintragen<br>Öffne&nbsp;<code>/volume1/docker/openai-relay/config.conf</code>&nbsp;und trage die URL ein:</p>



<pre class="wp-block-code"><code>N8N_WEBHOOK_URL=https://n8n.deine-domain.de/webhook/anruf-zusammenfassung</code></pre>



<p>Starte den openai-relay-Container neu. Jetzt sollte es funktionieren.</p>



<h3 class="wp-block-heading">4.10 Optional: KI legt nach der Verabschiedung selbst auf</h3>



<p><strong>Ulf</strong>: „Legt die KI eigentlich selbst auf?&#8220;<br><strong>Tanja</strong>: „Standardmäßig nicht. Sie verabschiedet sich und wartet dann. Der Anrufer muss auflegen.&#8220;<br><strong>Ulf</strong>: „Das ist unhöflich. Ich würde das ändern.&#8220;<br><strong>Tanja</strong>: „Du kannst. Es ist optional, aber es macht das Gespräch deutlich runder.&#8220;</p>



<p>Die Logik ist einfach: Wenn die KI sich verabschiedet – erkannt an Schlüsselwörtern im Transkript – startet ein Timer. Sagt der Anrufer innerhalb von 8 Sekunden nichts mehr, legt das System auf.<br>Alle Änderungen in&nbsp;<code>/volume1/docker/openai-relay/openai.js</code>:<br><strong>Änderung 1:</strong>&nbsp;Nach der Zeile&nbsp;<code>let transcriptLog = [];</code>&nbsp;(ca. Zeile 95) einfügen:</p>



<pre class="wp-block-code"><code>  let goodbyeTimer = null;
  let&amp;nbsp;goodbyeDetected&amp;nbsp;=&amp;nbsp;false;
  const GOODBYE_TIMEOUT_MS = 8000;
  const goodbyePattern = /wiedersehen|wiederh.ren|tsch.ss|sch.nen tag|guten tag noch/i;</code></pre>



<p><strong>Änderung 2:</strong>&nbsp;Im&nbsp;<code>response.audio_transcript.done</code>-Block, nach dem&nbsp;<code>transcriptLog.push</code>-Aufruf im&nbsp;<code>else</code>-Zweig (KI-Antwort), einfügen:</p>



<pre class="wp-block-code"><code>// Check if assistant said goodbye
              if (goodbyePattern.test(response.transcript)) {
                logger.info(`Goodbye detected for ${channelId}, starting ${GOODBYE_TIMEOUT_MS}ms hangup timer`);
                if (goodbyeTimer) clearTimeout(goodbyeTimer);
                goodbyeTimer = setTimeout(async () =&gt; {
                  logger.info(`Goodbye timeout reached for ${channelId}, hanging up`);
                  if (ws &amp;&amp; ws.readyState === WebSocket.OPEN) {
                    ws.close();
                  }
                  try {
                    const cd = sipMap.get(channelId);
                    if (cd &amp;&amp; cd.channel) {
                      await cd.channel.hangup();
                      logger.info(`Channel ${channelId} hung up after goodbye`);
                    }
                  } catch (e) {
                    logger.error(`Error hanging up channel ${channelId} after goodbye: ${e.message}`);
                  }
                }, GOODBYE_TIMEOUT_MS);
              }</code></pre>



<p><strong>Änderung 3:</strong>&nbsp;Im&nbsp;<code>conversation.item.created</code>-Block, nach&nbsp;<code>if (response.item.role === 'user') {</code>&nbsp;und vor&nbsp;<code>lastUserItemId = ...</code>, einfügen:</p>



<pre class="wp-block-code"><code>              if (goodbyeTimer) {
                clearTimeout(goodbyeTimer);
                goodbyeTimer = null;
                logger.info(`Goodbye timer cancelled for ${channelId}, user is speaking`);
              }</code></pre>



<p>Dieser Teil ist wichtig: Wenn der Anrufer nach der Verabschiedung doch nochmal etwas sagt, wird der Timer abgebrochen. Die KI antwortet dann nochmals – und startet den Timer bei der nächsten Verabschiedung neu.<br>Danach Container neu starten.</p>



<h2 class="wp-block-heading">5 Fazit</h2>



<p><strong>Einige Wochen später.</strong><br><strong>Ulf</strong> öffnet sein Handy. Eine E-Mail. Betreff: „Anruf von Klaus Müller (0171-…) &#8211; heute, 14:32 Uhr.&#8220;<br><strong>Ulf</strong> öffnet sie. Vollständiger Gesprächsverlauf. Name, Anliegen, Dringlichkeit, alles da. Drei Minuten Gespräch, in einer lesbaren E-Mail zusammengefasst.<br><strong>Ulf</strong>: „Hat funktioniert&#8220;.<br><strong>Tanja</strong>: „Das weiß ich&#8220;.<br><strong>Bernd</strong> schaut kurz rüber: „Ich habe auch eine Lösung gebaut. Ich habe meiner Frau gesagt, sie soll Anrufe entgegennehmen.&#8220;<br><strong>Ulf</strong>: „Und?&#8220;<br><strong>Bernd</strong> „Sie nimmt das Telefon nicht mehr ab.&#8220;</p>



<p>Was als Heimserver-Bastelprojekt begann, ist am Ende ein erstaunlich leistungsfähiges System. Ein Anrufer merkt kaum einen Unterschied zu einem echten Gespräch – die KI begrüßt freundlich, hört zu, fragt nach und verabschiedet sich. Wenige Sekunden später landet die vollständige Zusammenfassung im Postfach.</p>



<p><strong>Was gut funktioniert:</strong>&nbsp;Der größte Vorteil dieser Architektur ist die vollständige Kontrolle über die eigene Infrastruktur. Asterisk, n8n und das Relay laufen lokal auf der Synology – nur die KI-Verarbeitung findet bei OpenAI statt. Keine monatlichen Abokosten für Telefonie-Dienste, keine Abhängigkeit von externen SIP-Anbietern, volle Transparenz über die Gesprächsdaten.</p>



<p><strong>Wo es knifflig werden kann:</strong>&nbsp;Der schwierigste Teil ist erfahrungsgemäß die initiale Netzwerkkonfiguration – insbesondere&nbsp;<code>network_mode: host</code>, die Firewall-Regeln auf der Synology und die Cloudflare-Webhook-Freigabe. Wer hier sorgfältig vorgeht und jeden Schritt einzeln testet, spart sich viel Fehlersuche. Das Motto gilt auch hier: erst testen, dann weitermachen.</p>



<p><strong>Mögliche nächste Schritte:</strong></p>



<ul class="wp-block-list">
<li>Unterschiedliche System-Prompts je nach Rufnummer oder Tageszeit</li>



<li>Mehrsprachige Unterstützung</li>



<li>Integration in einen Kalender, damit die KI direkt Rückruftermine vereinbaren kann</li>



<li>Erweiterung des n8n-Workflows mit einer KI-basierten Zusammenfassung via Claude oder ChatGPT</li>
</ul>



<p>Bei Fragen oder Verbesserungsvorschlägen: Kommentar hinterlassen.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.foundic.org/de/ki-telefonassistent-openai-realtime-api-fritzbox-asterisk-synology-nas/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Mein digitaler KI Newsroom auf der Synology NAS: Wie n8n, ChatGPT, Claude und Flux-2-Flex täglich automatisch Artikel über KI recherchieren, schreiben und veröffentlichen</title>
		<link>https://www.foundic.org/de/ki-newsroom-n8n-synology-nas-automatisierung/</link>
					<comments>https://www.foundic.org/de/ki-newsroom-n8n-synology-nas-automatisierung/#respond</comments>
		
		<dc:creator><![CDATA[Michael Müller]]></dc:creator>
		<pubDate>Sun, 01 Mar 2026 19:07:00 +0000</pubDate>
				<category><![CDATA[Projekte]]></category>
		<guid isPermaLink="false">https://www.foundic.org/?p=812</guid>

					<description><![CDATA[Was du in diesem Tutorial baust, ist kein Google Alert. Es ist eine&#160;vollständige, KI-gesteuerte Nachrichtenredaktion&#160;– automatisiert von der ersten Quellensuche bis zum fertigen WordPress-Artikel. Das System durchforstet das Internet selbstständig nach den wichtigsten Entwicklungen im Bereich Künstliche Intelligenz. Als Gehirn dahinter dient n8n, ein selbst gehostetes Automatisierungswerkzeug, das verschiedene spezialisierte KI-Agenten zu einem digitalen Redaktionsteam zusammenschnürt. Dieses [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Was du in diesem Tutorial baust, ist kein Google Alert. Es ist eine&nbsp;<strong>vollständige, KI-gesteuerte Nachrichtenredaktion</strong>&nbsp;– automatisiert von der ersten Quellensuche bis zum fertigen WordPress-Artikel.</p>



<p>Das System durchforstet das Internet selbstständig nach den wichtigsten Entwicklungen im Bereich Künstliche Intelligenz. Als Gehirn dahinter dient <strong>n8n</strong>, ein selbst gehostetes Automatisierungswerkzeug, das verschiedene spezialisierte KI-Agenten zu einem digitalen Redaktionsteam zusammenschnürt. Dieses Team filtert die riesige Informationsflut aus RSS-Feeds, bewertet jeden Treffer nach Relevanz und verwandelt die besten Artikel in hochwertige Blog-Beiträge.</p>



<p><strong>Um diese Anleitung verständlicher zu machen, begleiten dich drei Personen:</strong><br>Die typischen Büro-Charaktere: Die kompetente IT-Kollegin, der selbsternannte Experte und der ehrliche Anfänger. Diese drei Perspektiven helfen dir, typische Stolperfallen zu erkennen und n8n wirklich zu verstehen.</p>



<p><strong>Tanja</strong>&nbsp;ist die IT-Expertin. Sie weiß, wie n8n funktioniert, erklärt geduldig und strukturiert – und lässt sich von schlechten Ratschlägen nicht aus der Ruhe bringen. Wenn du eine Frage hast, hat Tanja die Antwort.<br><strong>Bernd</strong>&nbsp;ist der selbsternannte „Experte“, der alles besser weiß – und meistens falsch liegt. Seine Abkürzungen und sein Halbwissen führen regelmäßig zu Problemen. Er steht für alle gefährlichen Mythen und schlechten Praktiken, die du vermeiden solltest.<br><strong>Ulf</strong>&nbsp;ist der Lernende, genau wie du. Er stellt die Fragen, die dir im Kopf herumschwirren, und braucht manchmal einen Vergleich aus dem Alltag, um IT zu verstehen. Wenn Ulf etwas nicht versteht, ist das völlig in Ordnung – dafür ist Tanja da.</p>



<p><strong>&#8222;Und… Action!&#8220;</strong></p>



<p><strong>Montag, 8:47 Uhr. Im Büro.</strong><br><strong>Ulf</strong> starrt auf seinen Bildschirm. Drei Browserfenster mit KI-Newsseiten, ein halbvolles Glas Kaffee, und das dumpfe Gefühl, dass er gerade wieder eine halbe Stunde damit verschwendet hat, Heise, Golem und t3n nacheinander durchzuklicken, um ja nichts zu verpassen.<br><strong>Ulf</strong>: „Ich will eigentlich nur die wichtigen KI-News haben&#8220;, murmelt er. „Ohne selbst stundenlang zu suchen.&#8220;<br><strong>Tanja</strong>, die seit zehn Minuten daneben sitzt und ihre Notizen liest, hebt den Kopf. „Dann hör auf, es manuell zu machen. Lass eine Maschine für dich suchen.&#8220;<br><strong>Bernd</strong> lehnt im Türrahmen. „Ich mach das auch automatisch. Ich hab einen Google Alert eingerichtet. Auf das Wort ‚KI&#8216;.&#8220; Er nickt sich selbst anerkennend zu. „Kriegst hundert Mails am Tag. Alles drin.&#8220;<br>Kurze Stille.<br><strong>Tanja</strong>: „Das ist ungefähr so, als würdest du den kompletten Supermarkt bestellen und dann schauen, was du davon essen kannst.&#8220;</p>



<p>Das Entscheidende: Das System arbeitet als&nbsp;<strong>„Human-in-the-Loop&#8220;-Konstruktion</strong>. Die KI übernimmt Recherche, Qualitätsprüfung und das Schreiben. Du als Admin behältst die Kontrolle – kein Artikel erscheint auf deiner Website, bevor du in WordPress grünes Licht gibst. So kombinierst du die Geschwindigkeit von KI mit menschlichem Urteilsvermögen. Schnell und trotzdem klug.<br>Technisch gesehen baust du ein&nbsp;<strong>Multi-Agenten-System</strong>, das die Stärken verschiedener Sprachmodelle geschickt kombiniert: GPT-4o-mini für die schnellen, massenhaften Bewertungsaufgaben – und Claude für die anspruchsvolle Artikelerstellung. Dazu kommt eine eigene Datenbank als „Langzeitgedächtnis&#8220;, die Duplikate verhindert und deine Redaktionsprozesse professionalisiert.</p>



<p><strong>Das Redaktionsteam &#8211; fünf Agenten:</strong></p>



<ul class="wp-block-list">
<li><strong>Agent 1:</strong>&nbsp;Recherche (RSS-Feeds, alle 2 Stunden)</li>



<li><strong>Agent 2:</strong>&nbsp;Redaktionelle Einzelbewertung (GPT-4o-mini, alle 4 Stunden)</li>



<li><strong>Agent 3:</strong>&nbsp;Content-Recherche &amp; Anreicherung (GPT-4o-mini + Tavily, täglich)</li>



<li><strong>Agent 4:</strong>&nbsp;Artikel schreiben + Coverbild erstellen (Claude + Flux-2-Flex, täglich)</li>



<li><strong>Agent 5:</strong>&nbsp;Veröffentlichen auf WordPress (täglich, mit menschlicher Freigabe)</li>
</ul>



<h2 class="wp-block-heading">2 Technische Beschreibung</h2>



<h3 class="wp-block-heading">2.1 Systemarchitektur</h3>



<p><strong>Ulf</strong>: „Warte mal kurz, die fünf Agenten reden die miteinander? Wie im Büro, so mit Slack oder so?&#8220;<br><strong>Tanja</strong> schüttelt den Kopf: „Stell dir eine Fabrik vor. Jede Abteilung macht ihren Job und legt das Ergebnis ins Regal. Die nächste Abteilung holt es von dort ab. Niemand ruft niemanden an.&#8220;<br>„Das Regal&#8220;, ergänzt <strong>Tanja</strong>, „ist die Datenbank.&#8220;<br><strong>Bernd</strong>: „Ich hätte die alle einfach miteinander verbunden. Direkt. Viel einfacher.&#8220;<br><strong>Tanja</strong>: „Dann hast du ein System, das ausfällt, wenn einer der fünf Agenten einen Fehler macht, und du weißt nicht mehr, wo. Die Datenbank ist der Schlüssel. Jeder Agent liest daraus, schreibt zurück, und setzt einen Status. So weiß jeder, was der andere getan hat – ohne direkt miteinander sprechen zu müssen.&#8220;</p>



<p>Der KI Newsroom folgt einer <strong>Pipeline-Architektur</strong>: Fünf spezialisierte n8n-Workflows arbeiten sequenziell, jeder übernimmt genau eine Aufgabe. Der Schlüssel, der sie zusammenhält, ist eine gemeinsame <strong>PostgreSQL-Datenbank</strong> als zentrales Gedächtnis. Kein Agent spricht direkt mit einem anderen – sie kommunizieren ausschließlich über die Datenbank, indem sie Datensätze lesen, verarbeiten und deren Status hochsetzen. Die gesamte Infrastruktur läuft <strong>self-hosted auf einer Synology NAS</strong> im Docker-Betrieb.</p>



<pre class="wp-block-code"><code>&#91;Internet / RSS-Feeds]
        ↓
  A1: Recherche         → ki_artikel (Status: NEU)
        ↓
  A2: Bewertung         → ki_artikel (Status: BEWERTET)
        ↓
  A3: Content-Recherche → ki_story   (Status: ANGEREICHERT)
        ↓
  A4: Artikel + Bild    → ki_artikel (Status: PUBLISH_READY)
        ↓
  A5: WordPress         → ki_artikel (Status: PUBLISHED)
        ↓
  &#91;WordPress / foundic.org]</code></pre>



<h3 class="wp-block-heading">2.2 Datenbankschema</h3>



<p>Die Datenbank besteht aus drei Tabellen – stell sie dir wie drei verschiedene Schubladen in einem Aktenschrank vor.</p>



<ul class="wp-block-list">
<li><strong><code>ki_artikel</code></strong>&nbsp;ist die große Hauptschublade. Hier landet jeder eingelesene RSS-Artikel und bleibt dort bis zur Veröffentlichung. Die Tabelle speichert Rohdaten aus dem Feed, KI-Bewertungsscores, fertige WordPress-Inhalte und den aktuellen Workflow-Status. Das Feld&nbsp;<code>url_normalized</code>&nbsp;verhindert Duplikate: Tracking-Parameter wie&nbsp;<code>utm_source</code>, das&nbsp;<code>www.</code>-Präfix und überflüssige Trailing Slashes werden aus URLs entfernt, bevor ein Artikel eingetragen wird. So landen Heise-Links mit und ohne&nbsp;<code>?utm_campaign=newsletter</code>&nbsp;nicht doppelt in der Datenbank.</li>



<li><strong><code>ki_story</code></strong>&nbsp;ist die Kreativschublade. Hier liegt der angereicherte, tiefenrecherchierte Inhalt – der von Agent 3 erstellte Hintergrundtext und später der von Claude verfasste fertige WordPress-Artikel. Jede Story ist genau einem Eintrag in&nbsp;<code>ki_artikel</code>&nbsp;zugeordnet.</li>



<li><strong><code>ki_artikel_edges</code></strong>&nbsp;ist die Verbindungsschublade. Wenn Tavily bei der Recherche verwandte Webseiten findet, dokumentiert diese Tabelle die Verbindung: Welcher Artikel hat welche Quelle gefunden? Mit welchem Suchbegriff? Auf welchem Ranking-Platz? So entsteht im Hintergrund ein kleines Wissensnetz aus verlinkten Artikeln.</li>
</ul>



<h3 class="wp-block-heading">2.3 Die fünf Agenten im Detail</h3>



<p><strong>Agent 1 &#8211; Recherche (alle 2 Stunden):</strong>&nbsp;22 parallele RSS-Feed-Leser versorgen das System mit Nachrichten aus der gesamten deutschsprachigen Tech- und Qualitätspresse: Heise, Golem, t3n, Computerwoche, FAZ, Handelsblatt, Spiegel, Süddeutsche und viele mehr. Jeder Feed ist mit einem Quellnamen gelabelt. Ein Postgres-Node mit&nbsp;<code>Skip on Conflict</code>verhindert doppelte Einträge; die URL-Normalisierung via JavaScript entfernt vor dem Speichern alle Tracking-Parameter.<br><strong>Agent 2 &#8211; Bewertung (alle 4 Stunden):</strong>&nbsp;Ein Basic LLM Chain-Node mit GPT-4o-mini bewertet jeden neuen Artikel auf zwei Dimensionen: KI-Anwendungsrelevanz und KI-Entwicklungsbedeutung (je 0–10). Die Gesamtnote gewichtet Anwendungsrelevanz mit 60 % und Entwicklungsbedeutung mit 40 %. Zusätzlich ordnet die KI jeden Artikel einer von 12 vordefinierten Subkategorien zu.<br><strong>Agent 3 &#8211; Content-Recherche (täglich):</strong>&nbsp;Artikel mit&nbsp;<code>score_gesamt &gt;= 7,5</code>&nbsp;werden tiefenrecherchiert. Der Workflow lädt den Volltext von der Quellseite, prüft die Textqualität und ergänzt mit bis zu 20 Tavily-Suchergebnissen. GPT-4o-mini fasst alles zu einem strukturierten Hintergrundtext zusammen.<br><strong>Agent 4 &#8211; Artikel + Bild (täglich):</strong>&nbsp;Der Artikel mit dem höchsten Score geht an Claude Sonnet, der daraus einen rechtskonformen WordPress-Artikel schreibt. Gleichzeitig generiert Flux-2-Flex ein eigenes Coverbild im Editorial-Flat-Design-Stil.<br><strong>Agent 5 &#8211; WordPress (täglich):</strong>&nbsp;Fertige Artikel landen zunächst als Entwurf in WordPress – und warten auf deine Freigabe. Das ist der Human-in-the-Loop-Kontrollpunkt.</p>



<h3 class="wp-block-heading">2.4 Technologien &amp; Kosten</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Komponente</th><th>Technologie</th></tr></thead><tbody><tr><td>Orchestrierung</td><td>n8n (self-hosted, Docker, Synology NAS)</td></tr><tr><td>Datenbank &amp; Monitoring</td><td>PostgreSQL + Metabase</td></tr><tr><td>Bewertung &amp; Recherche</td><td>GPT-4o-mini (OpenAI) + Tavily</td></tr><tr><td>Artikel-Erstellung</td><td>Claude Sonnet (Anthropic)</td></tr><tr><td>Bildgenerierung</td><td>Flux-2-Flex (Black Forest Labs)</td></tr><tr><td>Publikation</td><td>WordPress REST API</td></tr></tbody></table></figure>



<p>Bei täglicher Publikation eines Artikels bleiben die monatlichen API-Kosten typischerweise <strong>unter 5 Euro</strong> – dank GPT-4o-mini für das hohe Volumen (Bewertung + Recherche) und Claude Sonnet nur für den einzelnen, täglich erscheinenden Artikel. Flux-2-Flex kostet ca. 1–2 Cent pro Bild, Tavily ist bis 1.000 Suchen/Monat kostenlos.</p>



<h2 class="wp-block-heading">3 Umsetzung in n8n</h2>



<h3 class="wp-block-heading">3.1 Datenbank-Setup</h3>



<p><strong>Tanja</strong>: „Bevor wir die Agenten bauen, brauchen wir das Fundament. Die Datenbank.&#8220;<br><strong>Ulf</strong> runzelt die Stirn: „Warum können wir nicht einfach alles in Excel speichern?&#8220;<br><strong>Tanja</strong>: „Weil 500 Artikel pro Tag in Excel so aussehen wie ein Stadion nach dem Derbysieg – alles durcheinander, nichts mehr auffindbar.&#8220;<br><strong>Bernd</strong>: „Ich hab mal alle Kundendaten in einer Excel-Datei gehabt, hat super funktioniert. Bis ich aus Versehen die falsche Spalte gelöscht hab.&#8220;<br><strong>Tanja</strong> ignoriert ihn: „Wir nutzen PostgreSQL. Das ist eine Datenbank, die auf der NAS läuft, Dinge ordentlich wegschreibt und auf Anfrage blitzschnell wieder rausgibt. n8n redet mit ihr wie ein Büro mit seinem Aktenschrank.&#8220;</p>



<h4 class="wp-block-heading">3.1.1 Die Verbindung herstellen (Credentials)</h4>



<p><strong>Tanja</strong>: &#8222;Keine Panik – das klingt komplizierter als es ist. Du musst n8n nur einmalig sagen, wo deine Datenbank wohnt und wie das Passwort lautet. Danach merkt es sich das.&#8220;</p>



<ol class="wp-block-list">
<li>Logge dich in deine&nbsp;<strong>n8n-Oberfläche</strong>&nbsp;auf der NAS ein</li>



<li>Gehe links auf&nbsp;<strong>Start from scratch</strong>&nbsp;-&gt;&nbsp;<strong>Add first step</strong>&nbsp;-&gt; „+&#8220; -&gt; suche nach „Postgres&#8220; -&gt; wähle „Execute a SQL query&#8220; aus -&gt; Credential to connect with:&nbsp;<strong>„Create a new Credential&#8220;</strong></li>
</ol>



<p>Wie man n8n mit PostGres SQL Datenbank auf einer Synology Diskstation am Beispiel einer DS1621+ installiert findest Du in dem Artikel <a href="https://www.foundic.org/n8n-selbst-hosten-synology-nas-docker-installation/">https://www.foundic.org/n8n-selbst-hosten-synology-nas-docker-installation</a>.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e44008515ad&quot;}" data-wp-interactive="core/image" data-wp-key="69e44008515ad" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="683" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-1-postgres-auswaehlen-1024x683.png" alt="BILD 1 - n8n - postgres node auswählen" class="wp-image-815" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-1-postgres-auswaehlen-1024x683.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-1-postgres-auswaehlen-300x200.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-1-postgres-auswaehlen-768x512.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-1-postgres-auswaehlen.png 1536w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 1 &#8211; n8n &#8211; postgres node auswählen</figcaption></figure>



<ol start="3" class="wp-block-list">
<li>Jetzt musst du die Daten eingeben, die du im Synology Container Manager findest unter Container -&gt; postgres container -&gt; Details
<ul class="wp-block-list">
<li><strong>Host:</strong>&nbsp;IP-Adresse oder Containername (wenn im gleichen Projekt)</li>



<li><strong>Database:</strong>&nbsp;Meistens&nbsp;<code>postgres</code>&nbsp;oder&nbsp;<code>n8n_db</code>&nbsp;(je nachdem, was bei der Installation als&nbsp;<code>POSTGRES_DB</code>&nbsp;angegeben wurde)</li>



<li><strong>User:</strong>&nbsp;Der Name, den du vergeben hast (oft&nbsp;<code>postgres</code>&nbsp;oder&nbsp;<code>admin</code>)</li>



<li><strong>Password:</strong>&nbsp;Dein festgelegtes Passwort</li>
</ul>
</li>
</ol>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440085239a&quot;}" data-wp-interactive="core/image" data-wp-key="69e440085239a" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="683" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-2-Container-Manager-details-aus-dem-postgres-container-1024x683.png" alt="BILD 2 - Container Manager - details aus dem postgres container" class="wp-image-817" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-2-Container-Manager-details-aus-dem-postgres-container-1024x683.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-2-Container-Manager-details-aus-dem-postgres-container-300x200.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-2-Container-Manager-details-aus-dem-postgres-container-768x512.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-2-Container-Manager-details-aus-dem-postgres-container.png 1536w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 2 &#8211; Container Manager &#8211; details aus dem postgres container</figcaption></figure>



<ol start="4" class="wp-block-list">
<li>Klicke auf&nbsp;<strong>Save</strong>. Wenn oben ein grünes Schild mit „Connection tested successfully“ erscheint, steht die Leitung!</li>



<li>Nenne ihn oben links in der Workflow Übersicht:&nbsp;<code>Set-up Database</code></li>
</ol>



<h4 class="wp-block-heading">3.1.2: Erste Tabellen in der Datenbank erstellen</h4>



<p>Die Tabelle&nbsp;<code>ki_artikel</code>&nbsp;ist das&nbsp;<strong>zentrale digitale Gedächtnis</strong>&nbsp;deines Newsrooms – hier landen alle gesammelten Nachrichten, Bewertungen und der Veröffentlichungsstatus.<br>Stell dir vor, du richtest einen neuen Aktenschrank ein. Bevor du Dinge hineinlegen kannst, musst du die Fächer beschriften. Genau das macht das folgende SQL-Skript: Es legt die Fächerstruktur an.</p>



<ol class="wp-block-list">
<li>Schließe das Credential-Fenster (oben rechts auf das&nbsp;<strong>X</strong>&nbsp;klicken).</li>



<li>Du befindest dich nun wieder im Fenster der Postgres-Node (<strong>Execute a SQL query</strong>), ggf. Doppel Klick auf &#8222;Execute a SQL query&#8220;</li>



<li>Lösche die&nbsp;<strong>1</strong>&nbsp;im Feld&nbsp;<strong>Query</strong>&nbsp;komplett heraus.</li>



<li>Kopiere das folgende SQL-Skript und füge es dort ein:</li>
</ol>



<pre class="wp-block-code"><code>CREATE TABLE ki_artikel (
  -- Eindeutige ID
  id SERIAL PRIMARY KEY,

  -- Original-Daten
  url VARCHAR(500) UNIQUE NOT NULL,
  title TEXT NOT NULL,
  description TEXT,
  content TEXT, -- für später
  source VARCHAR(200) NOT NULL, -- z.B. 'Heise'
  published_date TIMESTAMP,
  image_url TEXT,
  source_type TEXT  -- z.B. 'rss'
  first_seen_at TIMESTAMPTZ NOT NULL DEFAULT now()
  url_normalized TEXT

  -- Workflow-Status
  status&amp;nbsp;VARCHAR(50),

  -- Bewertung
  score_relevanz INTEGER,
  score_bedeutung INTEGER,
  score_gesamt DECIMAL(3,1),
  subkategorie VARCHAR(80) DEFAULT NULL,
  bewertung_begruendung TEXT,

  -- Zeitstempel
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Index für schnelle Abfragen (Top-News)
CREATE INDEX idx_published_date ON ki_artikel(status, published_date DESC);
CREATE INDEX ki_artikel_url_normalized_idx ON ki_artikel(url_normalized);</code></pre>



<p>Klicke auf&nbsp;<strong>Execute step</strong>.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400852c36&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400852c36" class="wp-block-image aligncenter size-full wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="1024" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-3-n8n-Execute-a-SQL-query-SQL-Skript.png" alt="BILD 3 - n8n - Execute a SQL query - SQL Skript" class="wp-image-819" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-3-n8n-Execute-a-SQL-query-SQL-Skript.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-3-n8n-Execute-a-SQL-query-SQL-Skript-300x300.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-3-n8n-Execute-a-SQL-query-SQL-Skript-150x150.png 150w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-3-n8n-Execute-a-SQL-query-SQL-Skript-768x768.png 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 3 &#8211; n8n &#8211; Execute a SQL query &#8211; SQL Skript</figcaption></figure>



<p>Danach erstellst du zwei weitere Tabellen. Die erste verbindet Artikel miteinander (<code>ki_artikel_edges</code>), die zweite speichert den angereicherten Redaktionsinhalt (<code>ki_story</code>).<br><strong>Tabelle ki_artikel_edges</strong>&nbsp;– das Verbindungsnetz zwischen Artikeln:</p>



<pre class="wp-block-code"><code>CREATE TABLE IF NOT EXISTS ki_artikel_edges (
  id BIGSERIAL PRIMARY KEY,

  from_artikel_id BIGINT NOT NULL
    REFERENCES ki_artikel(id) ON DELETE CASCADE,

  to_artikel_id BIGINT NOT NULL
    REFERENCES ki_artikel(id) ON DELETE CASCADE,

  relation_type TEXT NOT NULL,     -- z.B. 'tavily_related'
  query TEXT,                      -- optional: Suchquery
  rank INT,                        -- Reihenfolge im Tavily Result
  score NUMERIC,                   -- optional: Tavily score/relevance
  retrieved_at TIMESTAMPTZ NOT NULL DEFAULT now(),

  UNIQUE (from_artikel_id, to_artikel_id, relation_type)
);

CREATE INDEX IF NOT EXISTS ki_artikel_edges_from_idx
  ON ki_artikel_edges(from_artikel_id);

CREATE INDEX IF NOT EXISTS ki_artikel_edges_to_idx
  ON ki_artikel_edges(to_artikel_id);

CREATE INDEX IF NOT EXISTS ki_artikel_edges_type_idx
  ON ki_artikel_edges(relation_type);</code></pre>



<p><strong>Tabelle ki_story</strong>&nbsp;– der Ort, an dem die fertigen Artikel reifen:</p>



<pre class="wp-block-code"><code>CREATE TABLE IF NOT EXISTS ki_story (
  id BIGSERIAL PRIMARY KEY,

  primary_artikel_id BIGINT NOT NULL
    REFERENCES ki_artikel(id) ON DELETE RESTRICT,

  content_enriched TEXT NOT NULL,
  enrichment_source TEXT,          -- 'direct' | 'search_llm'
  score_gesamt_enriched NUMERIC(4,2),
  tavily_link_count INTEGER,
  status TEXT NOT NULL DEFAULT 'DRAFT',
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),

  -- WordPress
  wp_title TEXT,
  wp_content TEXT,
  wp_excerpt TEXT,
  wp_tags TEXT,
  image_file_path TEXT,
  wordpress_post_id BIGINT,
  wordpress_url TEXT
);

CREATE INDEX IF NOT EXISTS ki_story_primary_idx
  ON ki_story(primary_artikel_id);</code></pre>



<h4 class="wp-block-heading">3.1.3: Workflow-Status Logik</h4>



<p>Das&nbsp;<code>status</code>-Feld in&nbsp;<code>ki_artikel</code>&nbsp;ist die Ampelanlage deines Systems. Jeder Agent schaut, ob eine Ampel auf sein Farbe steht, bearbeitet den Artikel und schaltet die Ampel weiter:</p>



<ul class="wp-block-list">
<li><code>NEU</code>&nbsp;(Insert)</li>



<li><code>BEWERTET</code>&nbsp;(Bewertung fertig)</li>



<li><code>ANGEREICHERT</code>&nbsp;(Hintergrundtext fertig)</li>



<li><code>PUBLISH_READY</code>&nbsp;(Artikel gezogen/„reserviert“)</li>



<li><code>PUBLISHED</code>&nbsp;(WordPress veröffentlicht)</li>



<li><code>PUBLISH_BLOCKED</code> (wenn irgendwas rechtlich/technisch nicht passt)</li>
</ul>



<h3 class="wp-block-heading">3.2 Agent 1: Recherche über RSS Feeds</h3>



<p><strong>Ulf</strong>: „RSS-Feeds, sist das nicht Technologie von vor zwanzig Jahren?&#8220;<br><strong>Tanja</strong>: „Fußball gibt es seit 150 Jahren, trotzdem ist es die effektivste Art, 22 Leute auf einem Feld zu koordinieren. RSS ist das Gleiche: simpel, robust, funktioniert überall.&#8220;<br><strong>Bernd</strong>: „Ich habe gehört, RSS ist tot&#8220;.<br><strong>Tanja</strong>: „Dann haben Heise, Spiegel, FAZ und die Süddeutsche es noch nicht mitbekommen. Die betreiben alle noch aktiv RSS-Feeds.&#8220;</p>



<h4 class="wp-block-heading">3.2.1 Den Arbeitsplatz einrichten</h4>



<ol class="wp-block-list">
<li>Gehe zurück zur Workflow-Übersicht und klicke auf&nbsp;<strong>Create new workflow</strong></li>



<li>Nenne ihn oben links:&nbsp;<code>1 Agent: Recherche über RSS Feeds</code></li>



<li>Klicke auf&nbsp;<strong>Add First Step</strong>&nbsp;und wähle&nbsp;<strong>Schedule Trigger</strong>
<ul class="wp-block-list">
<li>Trigger Interval: Hours</li>



<li>Stelle ihn zunächst auf&nbsp;<strong>Manual</strong>&nbsp;(= Custom Cron) – damit der Trigger beim Bauen nicht ständig feuert. Den echten Takt stellst du am Ende ein.</li>



<li>Hours Between Triggers: 2</li>



<li>Trigger at Minute: 0</li>
</ul>
</li>
</ol>



<h4 class="wp-block-heading">3.2.2 Die Quellen anzapfen (RSS-Feed)</h4>



<ol class="wp-block-list">
<li>Klicke auf das&nbsp;<strong>+</strong>&nbsp;hinter dem Schedule-Trigger</li>



<li>Suche nach der Node&nbsp;<strong>RSS Feed Read</strong>
<ul class="wp-block-list">
<li>Node: rssFeedRead</li>



<li>URL: RSS-Feed eintragen (z.B. <code>https://www.heise.de/rss/heise-atom.xml</code>)</li>
</ul>
</li>



<li>Klicke auf&nbsp;<strong>Test Step</strong>. Du solltest jetzt eine Liste mit Titeln und Links sehen</li>



<li>Du kannst beliebig viele RSS Feed Reader parallel in den Workflow setzen und mit dem Trigger verbinden. Klicke dazu auf den Ausgangspunkt des Triggers und dann auf den Eingangspunkt des jeweiligen RSS Feed Readers.</li>
</ol>



<h4 class="wp-block-heading">3.2.3 RSS Feed die Quelle zuordnen</h4>



<ol class="wp-block-list">
<li>Klicke auf das&nbsp;<strong>+</strong>&nbsp;Symbol am Ausgang deiner RSS-Nodes</li>



<li>Suche nach der Node&nbsp;<strong>Edit Fields</strong> (Brauchst diesen Node für jeden RSS-Feed)</li>



<li><strong>Einstellung:</strong>&nbsp;* Klicke auf&nbsp;<strong>„Add Field“</strong>&nbsp;-&gt;&nbsp;<strong>„String“</strong>.
<ul class="wp-block-list">
<li>Node: Edit Fields</li>



<li>Name des Feldes:&nbsp;<strong><code>source_name</code></strong> -&gt; String</li>



<li>Wert (Value):&nbsp;z.B. <strong><code>Heise</code></strong></li>



<li>Include Other Input Fields: aktivieren</li>
</ul>
</li>



<li><strong>Wiederholung:</strong>&nbsp;diese zwei Knoten für alle Deine weitere RSS-Feeds (RSS Feed -&gt; Edit Fields -&gt; Wert:&nbsp;<code>abc</code>) die Du regelmäßig auslesen möchtest.</li>
</ol>



<h4 class="wp-block-heading">3.2.4 Archiv in Datenbank aufbauen</h4>



<p>Jetzt zeigst du n8n, wo das Archiv liegt – und wie die Zeitungsschnipsel dort einsortiert werden. Denk an einen Bibliothekar, der eingehende Bücher nach einem festen Schema einräumt.</p>



<ol class="wp-block-list">
<li>Klicke auf das&nbsp;<strong>+</strong>&nbsp;am Ausgang deiner Edit Fields-Nodes</li>



<li>Suche nach&nbsp;<strong>Postgres</strong>&nbsp;und wähle „Insert rows in a table&#8220; aus:
<ul class="wp-block-list">
<li>Node: Insert rows in table</li>



<li>Credential to connect with: deine&nbsp;<code>n8n-postgres</code>-Verbindung aus Schritt 3.1.1</li>



<li>Operation: Insert</li>



<li>Schema: From list: public</li>



<li>Tabel: From list: <code>ki_artikel</code></li>



<li>Mapping Column Mode: Map Each Column Manually (Daten einsortieren)</li>
</ul>
</li>



<li>Jetzt kommt der wichtigste Teil: Du musst n8n sagen, welches RSS-Feld in welche Datenbankspalte gehört. Klicke auf&nbsp;<strong>Add Column</strong>&nbsp;und trage nacheinander folgende Zuordnungen ein:</li>
</ol>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Spalte (Column)</th><th>Wert (Value) – So machst du es:</th></tr></thead><tbody><tr><td>id</td><td>Diese Zeile komplett löschen – die ID zählt automatisch hoch</td></tr><tr><td>titel</td><td>Klicke in das Feld. Suche links im Menü unter „RSS Feed Read“ <code>title</code> und ziehe&nbsp;&nbsp;per drag&amp;drop in <code>title</code>, oder alternativ<br>{{ $json.title }}</td></tr><tr><td>url</td><td>{{ $json.link }}</td></tr><tr><td>description</td><td>{{ $json.summary || $json.content || $json.contentSnippet || &#8220; }}</td></tr><tr><td>source</td><td>{{ $json.source_name }}</td></tr><tr><td>published_date</td><td>{{ $json.isoDate }}</td></tr><tr><td>image_url</td><td>{{ $json.enclosure?.url || &#8220; }}</td></tr><tr><td>status</td><td><code>NEU</code>&nbsp;(von Hand eintippen, nicht aus dem Menü wählen)</td></tr><tr><td>source_type</td><td><code>rss</code>&nbsp;(von Hand eintippen)</td></tr><tr><td>url_normalized</td><td>Expression (siehe Code unten)</td></tr></tbody></table></figure>



<p>Für&nbsp;<code>url_normalized</code>&nbsp;kopiere diesen JavaScript-Ausdruck in das Value-Feld:</p>



<pre class="wp-block-code"><code>{{ 
(() =&gt; {
  const raw = $json.link || $json.url || "";
  try {
    const u = new URL(raw.startsWith("http") ? raw : "https://" + raw);

    // Fragment entfernen
    u.hash = "";

    // Tracking-Parameter entfernen
    const dropExact = new Set(&#91;
      "fbclid","gclid","dclid","msclkid","igshid",
      "mc_cid","mc_eid","mkt_tok","yclid","cmpid"
    ]);

    for (const k of Array.from(u.searchParams.keys())) {
      const key = k.toLowerCase();
      if (key.startsWith("utm_") || dropExact.has(key)) {
        u.searchParams.delete(k);
      }
    }

    // Host &amp; Protokoll normalisieren
    u.hostname = u.hostname.replace(/^www\./i, "").toLowerCase();
    u.protocol = "https:";

    // Trailing slash nur bei Root entfernen
    if (u.pathname === "/") u.pathname = "";

    u.search = u.searchParams.toString()
      ? "?" + u.searchParams.toString()
      : "";

    return u.toString();
  } catch (e) {
    return raw;
  }
})()
}}</code></pre>



<p>Warum dieser Aufwand? Weil derselbe Artikel von Heise mit fünf verschiedenen Tracking-URLs auftauchen kann –&nbsp;<code>?utm_source=twitter</code>,&nbsp;<code>?utm_campaign=newsletter</code>&nbsp;usw. Ohne Normalisierung würde jede Variante als neuer Artikel landen. Mit diesem Code landen alle Varianten als ein einziger Datensatz.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400853bc2&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400853bc2" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="683" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-4-n8n-RSS-Feed-auf-Datenbankstruktur-gemapped-1024x683.png" alt="BILD 4 - n8n - RSS-Feed auf Datenbankstruktur gemapped" class="wp-image-820" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-4-n8n-RSS-Feed-auf-Datenbankstruktur-gemapped-1024x683.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-4-n8n-RSS-Feed-auf-Datenbankstruktur-gemapped-300x200.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-4-n8n-RSS-Feed-auf-Datenbankstruktur-gemapped-768x512.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-4-n8n-RSS-Feed-auf-Datenbankstruktur-gemapped.png 1536w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 4 &#8211; n8n &#8211; RSS-Feed auf Datenbankstruktur gemapped</figcaption></figure>



<ol start="4" class="wp-block-list">
<li>Lösche alle anderen vorausgefüllten „Values to Update&#8220;, damit nur die oben definierten Felder geschrieben werden.</li>



<li>Ganz unten:&nbsp;<strong>Options</strong>&nbsp;→&nbsp;<strong>Add option</strong>&nbsp;→&nbsp;<strong>Skip on Conflict</strong>&nbsp;aktivieren. Damit wird ein Artikel, dessen URL bereits in der Datenbank liegt, einfach übersprungen statt einen Fehler zu werfen.</li>



<li>Testlauf: Klicke auf den orangefarbenen Button&nbsp;<strong>„Execute Workflow&#8220;</strong>. Was jetzt passieren sollte: n8n zieht die News aus den Feeds (grüne Zahlen erscheinen), schickt sie zur Postgres-Node (nächste grüne Zahl) und speichert sie auf deiner NAS. Wenn du die Zahlen siehst – Glückwunsch, dein erstes Archiv lebt.</li>
</ol>



<h4 class="wp-block-heading">3.2.5 Workflow veröffentlichen</h4>



<p>Stelle den Schedule Trigger auf&nbsp;<strong>2 Stunden</strong>&nbsp;und aktiviere den Workflow über&nbsp;<strong>Publish</strong>.</p>



<figure class="wp-block-image aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="683" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-5-n8n-Fertiger-Workflow-1-Agent-Recherche-ueber-RSS-Feeds-1024x683.png" alt="BILD 5 - n8n - Fertiger Workflow - 1 Agent - Recherche über RSS Feeds" class="wp-image-822" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-5-n8n-Fertiger-Workflow-1-Agent-Recherche-ueber-RSS-Feeds-1024x683.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-5-n8n-Fertiger-Workflow-1-Agent-Recherche-ueber-RSS-Feeds-300x200.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-5-n8n-Fertiger-Workflow-1-Agent-Recherche-ueber-RSS-Feeds-768x512.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-5-n8n-Fertiger-Workflow-1-Agent-Recherche-ueber-RSS-Feeds.png 1536w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">BILD 5 &#8211; n8n &#8211; Fertiger Workflow &#8211; 1 Agent &#8211; Recherche über RSS Feeds</figcaption></figure>



<h3 class="wp-block-heading">3.3 Agent 2: Redaktionelle Einzelbewertung</h3>



<p><strong>Ulf</strong>: „Okay, wir haben jetzt ein Archiv voller Artikel, aber wie wissen wir, welche davon gut sind?&#8220;<br><strong>Tanja</strong>: „Indem wir eine KI fragen, die liest Titel und Beschreibung, gibt eine Note von 0 bis 10 und ordnet den Artikel einer Kategorie zu.&#8220;<br><strong>Bernd</strong> schnaubt. „Ich bewerte das manuell. Mit Bauchgefühl. Das ist viel besser als jede KI.&#8220;<br><strong>Tanja</strong>: „Du hast gestern einen Artikel über ‚KI in der Landwirtschaft&#8216; als Top-News markiert. Wir schreiben einen Blog über KI-Tools für Wissensarbeiter.&#8220;<br>Stille.<br><strong>Bernd</strong>: „Es war ein interessanter Artikel&#8220;.</p>



<h4 class="wp-block-heading">3.3.1 Den Workflow starten</h4>



<ol class="wp-block-list">
<li>Gehe zurück zur Workflow-Übersicht und klicke auf&nbsp;<strong>Create new workflow</strong></li>



<li>Nenne ihn oben links:&nbsp;<code>2 Agent: Redaktionelle Einzelbewertung</code></li>



<li>Füge einen&nbsp;<strong>Schedule Trigger</strong>&nbsp;hinzu:
<ul class="wp-block-list">
<li>Trigger Interval: Hours<br>Stelle sie für den Anfang auf&nbsp;<strong>Manual</strong> (= Custom (Cron)), damit wir beim Bauen nicht ständig neue Daten ziehen. Später stellen wir sie auf „Alle 4 Stunden“</li>



<li>Hours Between Triggers: 4</li>



<li>Trigger at Minute: 0</li>
</ul>
</li>
</ol>



<h4 class="wp-block-heading">3.3.2 Datensatz aus Datenbank auslesen</h4>



<ol class="wp-block-list">
<li>Füge eine&nbsp;<strong>Postgres-Node „Execute a SQL query&#8220;</strong>&nbsp;hinzu:
<ul class="wp-block-list">
<li>Credtial to connect with: <code>n8n-postgres</code></li>



<li>Query:</li>
</ul>
</li>
</ol>



<pre class="wp-block-code"><code>SELECT id, title, description, url 
FROM ki_artikel 
WHERE status = 'NEU' 
LIMIT 5;</code></pre>



<p>Mit&nbsp;<code>LIMIT 5</code>&nbsp;starten wir ruhig &#8211; zum Testen reichen fünf Artikel. Später kannst du das Limit hochsetzen.</p>



<h4 class="wp-block-heading">3.3.3 Loop einbauen</h4>



<p>Die KI soll jeden Artikel einzeln bewerten – nicht alle auf einmal. Dafür kommt ein Loop-Node:</p>



<ul class="wp-block-list">
<li>Node:&nbsp;<strong>Loop Over Items</strong></li>



<li>Bartch Size: 1</li>



<li>Done: bleibt leer</li>



<li>Loop: nächster Knoten<br>Stell es dir vor wie ein Fließband: Artikel rein, bewerten, nächster Artikel.</li>
</ul>



<h4 class="wp-block-heading">3.3.4 Basic LLM Chain</h4>



<p><strong>Bernd</strong>: „Moment, wenn wir schon KI einsetzen, dann richtig. Ich würde hier GPT-5.2 nehmen. Das Beste vom Besten.&#8220;<br><strong>Tanja</strong> dreht sich zu ihm. „Wie viele Artikel bewertet Agent 2 pro Tag?&#8220;<br><strong>Bernd</strong> zuckt die Schultern. „Weiß ich nicht. Hundert? Zweihundert?&#8220;<br><strong>Tanja</strong>: „Nehmen wir 150. GPT-5.2 kostet etwa $15 pro Million Input-Token. GPT-4o-mini kostet $0,15 – also hundertmal weniger.&#8220; Sie schreibt zwei Zahlen auf einen Zettel. „Pro Artikel gehen wir von rund 500 Token für Titel und Beschreibung aus, plus nochmal 200 Token Ausgabe. Bei 150 Artikeln täglich und 30 Tagen im Monat kommst du mit GPT-4o auf etwa&nbsp;<strong>33 Euro im Monat</strong>. Nur für die Bewertung.&#8220;<br><strong>Ulf</strong>: „Und mit mini?&#8220;.<br><strong>Tanja</strong>: „33 Cent&#8220;<br>Kurze Pause.<br><strong>Bernd</strong>: „Aber, GPT-5.2 ist doch viel schlauer.&#8220;<br><strong>Tanaj</strong>: „Für diese Aufgabe brauchen wir kein Genie, wir fragen: Ist dieser Artikel relevant? Welche Kategorie? Begründung in 25 Wörtern. Das ist eine strukturierte Klassifikationsaufgabe – kein Raketenantrieb, kein Gedicht, keine Rechtsberatung. GPT-4o-mini löst das genauso zuverlässig wie der große Bruder. Der Unterschied: Geschwindigkeit und Preis.&#8220;<br><strong>Ulf</strong>: „Wann würde man dann das große Modell nehmen?&#8220;<br><strong>Tanja</strong>: „Agent 4. Artikel schreiben. Da steckt Nuancen drin, Argumentation, Stil, Urheberrechtssensibilität. Dafür nehmen wir Claude Sonnet. Aber für ‚Note 0 bis 10 vergeben&#8216; &#8211; da ist mini schlau genug und 100-mal günstiger.&#8220;<br><strong>Bernd</strong> schaut auf seinen Bildschirm. „Ich hätte trotzdem das große genommen.&#8220;<br><strong>Tanj</strong>: „Das weiß ich, deshalb entscheide ich das.&#8220;</p>



<p>Jetzt kommt das Herzstück von Agent 2. Warum der&nbsp;<strong>„Basic LLM Chain&#8220;</strong>&nbsp;und nicht der „AI Agent&#8220;? Ganz einfach: Der AI Agent ist wie ein Allrounder, der theoretisch Werkzeuge benutzen, recherchieren und selbst entscheiden kann. Wir brauchen hier aber nur einen einzigen Durchgang: Text rein -&gt; Prompt anwenden -&gt; JSON raus. Der Basic LLM Chain macht genau das &#8211; schneller und günstiger.</p>



<ul class="wp-block-list">
<li>Node:&nbsp;<strong>Basic LLM Chain</strong></li>



<li>Source for Prompt (User Message): Define below</li>



<li>Prompt (User Message):</li>
</ul>



<pre class="wp-block-code"><code>Rolle: Du bist eine kritische Analystin und KI-Trend-Scout.
Aufgabe: Bewerte den folgenden Artikel nach seinem Nutzen für interessierte KI-Anwender, die KI im Alltag (privat &amp; beruflich) besser einsetzen und zukünftige Entwicklungen verstehen wollen. Ordne den Artikel zudem präzise den vorgegebene Subkategorien zu.

Input-Daten:
Titel: {{ $json.title }}
Beschreibung: {{ $json.description }}

---

### 1. Strenge Bewertungs-Logik (Skala 0 bis 10):

KI-Anwendungsrelevanz (Nutzwert heute):
- 0–1: Kein KI-Bezug oder rein abstrakt / technisch ohne Nutzenableitung.
- 2–4: KI wird erwähnt, aber ohne konkrete Nutzungsideen.
- 5–6: Liefert Beispiele, Tools, Produktivitäts- oder Alltagsbezug.
- 7–8: Klare, übertragbare Use-Cases (Arbeit, Lernen, Organisation, Kreativität).
- 9–10: Hoher Mehrwert: verändert konkret, wie man KI sinnvoll nutzt.

KI-Entwicklungsbedeutung (Blick in die Zukunft):
- 0–1: Unbedeutend oder reine Randnotiz.
- 2–4: Allgemeine Entwicklung ohne Tiefgang.
- 5–6: Relevanter Trend (z. B. Copilots, Regulierung, KI im Alltag).
- 7–8: Wichtige Weichenstellung (z. B. neue Einsatzfelder, starke Verbreitung).
- 9–10: Paradigmenwechsel mit klaren Folgen für Nutzer:innen.

---

### 2. Subkategorien (Wähle EXAKT einen Namen aus dieser Liste):

1. Anwendungsfälle &amp; Best Practices (Konkretisierung: Praxisbeispiele, Alltag/Beruf, Produktivitäts-Szenarien)
2. Prompting (Konkretisierung: Operative Assets: Gebrauchsfertige Vorlagen, konkrete Befehlsketten und „Copy &amp; Paste“-Prompts für sofortige Ergebnisse)
3. Lernen &amp; Skill-Aufbau (Konkretisierung: Methodisches Wissen: Tutorials, Lernpfade, Konzepte wie Chain-of-Thought, Methodik, Erklärungen zum „Mitdenken“)
4. Tools &amp; Produkt-Updates (Konkretisierung: Software-Releases, neue Funktionen, UI-Änderungen)
5. Automatisierung &amp; Agenten (Konkretisierung: n8n/Zapier Workflows, Agent-Flows, APIs, Prozessautomatisierung)
6. KI-Kreativität (Konkretisierung: Fokus auf generative Medien-Erstellung: Bild, Video, Audio, Design jenseits reiner Text-Assistenz)
7. News &amp; Entwicklungen (Konkretisierung: Markt- &amp; Strategie-News, Trends, allgemeine Einordnung)
8. Modelle &amp; Open Source (Konkretisierung: LLMs, Open-Source-Modelle, GitHub-Projekte, technischer Deep Dive)
9. Hardware &amp; Lokale KI (Konkretisierung: Gadgets, AI-PCs, Chips wie Nvidia/NPU, Local-AI-Setups)
10. Sicherheit &amp; Privacy (Konkretisierung: Datenschutz, Security, sichere KI-Nutzung)
11. Ethik, Recht &amp; Politik (Konkretisierung: AI Act, Regulierung, Governance, Deepfakes)
12. Kein KI-Fokus (Fokus: Default-Kategorie für alle Inhalte ohne klaren KI-Nutzen oder KI-Bezug, allgemeine Technik-News oder Off-Topic)

WICHTIG: Wenn die Sub-Kategorie "Kein KI-Fokus" gewählt wird, dann müssen Anwendungsrelevanz &lt;= 1 UND Entwicklungsbedeutung &lt;= 1 sein.

---

### 3. Ausgabe-Format &amp; Validierung:
Erzeuge ausschließlich ein valides JSON-Objekt ohne Markdown-Formatierung.

WICHTIG: Das Feld "subkategorie" MUSS buchstabengetreu mit einem der oben genannten 12 Namen übereinstimmen. Ändere keine Sonderzeichen, erfinde keine neuen Namen und achte auf exakte Groß-/Kleinschreibung.

STRICT OUTPUT RULES:
- Gib GENAU EIN JSON-Objekt aus.
- Kein Text vor oder nach dem JSON.
- KEIN Komma nach der schließenden }.
- Verwende ausschließlich doppelte Anführungszeichen für JSON.

{
  "anwendungsrelevanz": Zahl,
  "entwicklungsbedeutung": Zahl,
  "subkategorie": "EXAKTER_NAME_AUS_LISTE",
  "begruendung": "Maximal 25 Wörter. Begründung der Kategorie + Begründung der  Anwendungsrelevanz und Entwicklungsbedeutung."
}</code></pre>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440085494c&quot;}" data-wp-interactive="core/image" data-wp-key="69e440085494c" class="wp-block-image aligncenter size-full wp-lightbox-container"><img loading="lazy" decoding="async" width="987" height="890" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-6-n8n-Node-Erster-Open-AI-Agent.png" alt="BILD 6 - n8n - Node - Erster Open AI Agent" class="wp-image-823" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-6-n8n-Node-Erster-Open-AI-Agent.png 987w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-6-n8n-Node-Erster-Open-AI-Agent-300x271.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-6-n8n-Node-Erster-Open-AI-Agent-768x693.png 768w" sizes="auto, (max-width: 987px) 100vw, 987px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 6 &#8211; n8n &#8211; Node &#8211; Erster Open AI Agent</figcaption></figure>



<p>Verbinde den Basic LLM Chain mit dem&nbsp;<strong>OpenAI Chat Model</strong>:</p>



<ul class="wp-block-list">
<li>Node: OpenAI Chat Model</li>



<li>Credential to connect with: OpenAI account</li>



<li>Model:&nbsp;<code>gpt-4o-mini</code></li>



<li>Use Response API: active</li>
</ul>



<h4 class="wp-block-heading">3.3.5 Code in JavaScript</h4>



<p>GPT-4o-mini liefert manchmal JSON mit Markdown-Umrandung zurück (Backticks,&nbsp;<code>json</code>-Tags). Dieser Code-Node räumt das auf und berechnet den Gesamtscore:</p>



<ul class="wp-block-list">
<li>Node: Code in JavaScript</li>



<li>Mode: Run Once for Each ITem</li>



<li>Language: JavaScript</li>
</ul>



<pre class="wp-block-code"><code>let raw = $json.text;
// Entfernt Backticks und säubert den Text
let clean = raw.replace(/```json/g, "").replace(/```/g, "").trim().replace(/,\s*$/, "");
let data = JSON.parse(clean);

// Falls die KI es in "output" verpackt hat
if (data.output) data = data.output;

// Nur EIN return-Block mit allen Feldern:
return {
  anwendungsrelevanz: Number(data.anwendungsrelevanz),
  entwicklungsbedeutung: Number(data.entwicklungsbedeutung),
  subkategorie: data.subkategorie,
  begruendung: data.begruendung,
  // Hier passiert die wichtige Berechnung für DECIMAL(3,1)
  score_gesamt: (Number(data.anwendungsrelevanz)*6 + Number(data.entwicklungsbedeutung)*4)/10
};</code></pre>



<p>Die Formel am Ende ist keine Magie: Anwendungsrelevanz zählt sechsfach, Entwicklungsbedeutung vierfach. Das teilen wir durch 10 – fertig ist ein Score zwischen 0 und 10, gespeichert als&nbsp;<code>DECIMAL(3,1)</code>.</p>



<h4 class="wp-block-heading">3.3.6 Merge Combine</h4>



<p>Jetzt haben wir ein Problem: Der Bewertungs-Code kennt nur die KI-Ergebnisse, aber nicht mehr die Datenbank-ID des Artikels. Ohne die ID können wir den Datensatz nicht aktualisieren. Der&nbsp;<strong>Merge-Node</strong>&nbsp;löst das: Er fügt die Datenbankfelder (inkl.&nbsp;<code>id</code>) und die Bewertungsfelder zu einem gemeinsamen Datensatz zusammen.</p>



<ul class="wp-block-list">
<li>Node:&nbsp;<strong>Merge Combine</strong></li>



<li>Mode: Combine</li>



<li>Combine by: Position</li>



<li>Number of Inputs: 2<br>Verbinde die zwei Eingänge: Ausgang „loop&#8220; des Loop Over Items-Nodes → Eingang 1 des Merge; Ausgang des Code-Nodes → Eingang 2 des Merge.</li>
</ul>



<figure class="wp-block-image aligncenter size-large"><img loading="lazy" decoding="async" width="1024" height="392" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-7-n8n-Node-Merge-Konfiguration-1024x392.png" alt="BILD 7 - n8n - Node - Merge Konfiguration" class="wp-image-824" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-7-n8n-Node-Merge-Konfiguration-1024x392.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-7-n8n-Node-Merge-Konfiguration-300x115.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-7-n8n-Node-Merge-Konfiguration-768x294.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-7-n8n-Node-Merge-Konfiguration.png 1529w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">BILD 7 &#8211; n8n &#8211; Node &#8211; Merge Konfiguration</figcaption></figure>



<h4 class="wp-block-heading">3.3.7 In Datenbank speichern</h4>



<ol class="wp-block-list">
<li>Füge einen&nbsp;<strong>Postgres-Node</strong>&nbsp;am Ende hinzu:
<ul class="wp-block-list">
<li>Node: Update rows in a table</li>



<li>Credential to connect with:&nbsp;<code>n8n-postgres</code></li>



<li>Operation: Update</li>



<li>Schema: public</li>



<li>Table:&nbsp;<code>ki_artikel</code></li>



<li>Mapping Column Mode: Map Each Column Manually</li>



<li>Columns to match on:&nbsp;<strong>id</strong></li>
</ul>
</li>
</ol>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Feld</th><th>Value</th></tr></thead><tbody><tr><td>id (using to match)</td><td>{{ $json.id }}</td></tr><tr><td>score_relevanz</td><td>{{ $json.anwendungsrelevanz }}</td></tr><tr><td>score_bedeutung</td><td>{{ $json.entwicklungsbedeutung }}</td></tr><tr><td>score_gesamt</td><td>{{ $json.score_gesamt }}</td></tr><tr><td>bewertung_begruendung</td><td>{{ $json.begruendung }}</td></tr><tr><td>status</td><td>BEWERTET</td></tr><tr><td>subkategorie</td><td>{{ $json.subkategorie }}</td></tr></tbody></table></figure>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e44008556f6&quot;}" data-wp-interactive="core/image" data-wp-key="69e44008556f6" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="836" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-8-n8n-Postgres-22Update-rows-in-tabel22-Konfiguration-1024x836.png" alt="BILD 8 - n8n - Postgres &quot;Update rows in tabel&quot; Konfiguration" class="wp-image-825" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-8-n8n-Postgres-22Update-rows-in-tabel22-Konfiguration-1024x836.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-8-n8n-Postgres-22Update-rows-in-tabel22-Konfiguration-300x245.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-8-n8n-Postgres-22Update-rows-in-tabel22-Konfiguration-768x627.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-8-n8n-Postgres-22Update-rows-in-tabel22-Konfiguration.png 1450w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 8 &#8211; n8n &#8211; Postgres &#8222;Update rows in tabel&#8220; Konfiguration</figcaption></figure>



<p>Verbinde den Ausgang dieses Nodes zurück mit dem&nbsp;<strong>Eingang des Loop Over Items-Nodes</strong>&nbsp;– so läuft die Schleife für alle abgerufenen Artikel durch.</p>



<h4 class="wp-block-heading">3.3.8 Workflow veröffentlichen</h4>



<p>Stelle den Schedule Trigger auf&nbsp;<strong>4 Stunden</strong>&nbsp;und aktiviere den Workflow über&nbsp;<strong>Publish</strong>.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e44008560d7&quot;}" data-wp-interactive="core/image" data-wp-key="69e44008560d7" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="635" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-9-n8n-Fertiger-Workflow-2-Agent-Redaktionelle-Einzelbewertung-1024x635.png" alt="BILD 9 - n8n - Fertiger Workflow - 2 Agent - Redaktionelle Einzelbewertung" class="wp-image-826" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-9-n8n-Fertiger-Workflow-2-Agent-Redaktionelle-Einzelbewertung-1024x635.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-9-n8n-Fertiger-Workflow-2-Agent-Redaktionelle-Einzelbewertung-300x186.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-9-n8n-Fertiger-Workflow-2-Agent-Redaktionelle-Einzelbewertung-768x476.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-9-n8n-Fertiger-Workflow-2-Agent-Redaktionelle-Einzelbewertung.png 1401w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 9 &#8211; n8n &#8211; Fertiger Workflow &#8211; 2 Agent &#8211; Redaktionelle Einzelbewertung</figcaption></figure>



<h3 class="wp-block-heading">3.4 Dashboard mit Metabase (Optional)</h3>



<p><strong>Ulf</strong>: „Moment, ich will mal sehen, was da in meiner Datenbank passiert. Wie schaue ich da rein?&#8220;<br><strong>Tanja</strong>: „Mit Metabase, das ist ein Dashboard-Tool, das sich direkt an deine PostgreSQL-Datenbank hängt. Du kannst dann Fragen stellen wie: ‚Wie viele Artikel wurden heute bewertet?&#8216; und bekommst eine Tabelle oder ein Diagramm zurück.&#8220;<br><strong>Bernd:</strong> „Ich guck einfach direkt in die Datenbank, mit dem Terminal. Ist professioneller.&#8220;<br><strong>Ulf</strong>: „Du hast letzte Woche eine Tabelle aus Versehen gelöscht, weil du ein Leerzeichen vergessen hast.&#8220;<br>Bernd hustet.</p>



<p>Metabase brauchst du nicht zwingend – die Agenten laufen auch ohne. Aber es ist hilfreich, wenn du einen schnellen Überblick willst: Wie viele Artikel wurden eingelesen? Wie verteilen sich die Scores? Welche Kategorien dominieren?</p>



<h4 class="wp-block-heading">3.4.1 Ordnerstruktur vorbereiten</h4>



<p>Metabase möchte seine eigenen Einstellungen (welche Fragen du gestellt hast, wie dein Dashboard aussieht) irgendwo speichern. Standardmäßig macht es das&nbsp;<em>innerhalb</em>&nbsp;des Containers. Wenn du den Container löschst oder updatest, ist dein Dashboard weg.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e44008568c4&quot;}" data-wp-interactive="core/image" data-wp-key="69e44008568c4" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="555" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-10-Container-Manager-metabase-Ordner-unter-docker-1-1024x555.png" alt="BILD 10 - Container Manager - metabase Ordner unter docker" class="wp-image-828" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-10-Container-Manager-metabase-Ordner-unter-docker-1-1024x555.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-10-Container-Manager-metabase-Ordner-unter-docker-1-300x163.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-10-Container-Manager-metabase-Ordner-unter-docker-1-768x416.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-10-Container-Manager-metabase-Ordner-unter-docker-1.png 1159w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 10 &#8211; Container Manager &#8211; metabase Ordner unter docker</figcaption></figure>



<p>Damit dein Dashboard &#8222;ewig&#8220; lebt, solltest du unter&nbsp;<strong>Volume-Einstellungen</strong>&nbsp;(im nächsten Schritt) einen Ordner auf deiner NAS verknüpfen:</p>



<ul class="wp-block-list">
<li><strong>Ordner:</strong>&nbsp;Erstelle auf deiner NAS einen Ordner&nbsp;<code>docker/metabase</code>.</li>
</ul>



<h4 class="wp-block-heading">3.4.2 Metabase einrichten</h4>



<ul class="wp-block-list">
<li>Image Name:&nbsp;<code>metabase/metabase</code></li>



<li>Port: standardmäßig 3000</li>
</ul>



<p>Vorgehensweise:</p>



<ol class="wp-block-list">
<li>Lade das Image im&nbsp;<strong>Container Manager</strong>&nbsp;auf der Synology herunter</li>
</ol>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e44008571d3&quot;}" data-wp-interactive="core/image" data-wp-key="69e44008571d3" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="753" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-10-Container-Manager-metabase-Ordner-unter-docker-1024x753.png" alt="BILD 11 - Container Manager - Image metabase/metabase auswählen und laden" class="wp-image-827" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-10-Container-Manager-metabase-Ordner-unter-docker-1024x753.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-10-Container-Manager-metabase-Ordner-unter-docker-300x221.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-10-Container-Manager-metabase-Ordner-unter-docker-768x565.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-10-Container-Manager-metabase-Ordner-unter-docker.png 1225w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 11 &#8211; Container Manager &#8211; Image metabase/metabase auswählen und laden</figcaption></figure>



<p>2. Führe das Image aus:&nbsp;<strong>metabase/metabase:latest</strong>&nbsp;→ Ausführen</p>



<ul class="wp-block-list">
<li>Containername:&nbsp;<code>metabase-newsroom</code></li>



<li>Port: 3000</li>



<li>Volume-Einstellungen:&nbsp;<strong>+ Ordner hinzufügen</strong>
<ul class="wp-block-list">
<li>Ordner&nbsp;<code>docker/metabase</code>&nbsp;auswählen (vorher auf der NAS erstellen)</li>



<li>Mount-Pfad:&nbsp;<code>/metabase.db</code>&nbsp;eintragen</li>
</ul>
</li>
</ul>



<ol start="2" class="wp-block-list">
<li></li>
</ol>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400857935&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400857935" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="751" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-12-Container-Manager-container-metabase-im-container-port-volume-1024x751.png" alt="BILD 12 - Container Manager - container metabase im container - port - volume" class="wp-image-829" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-12-Container-Manager-container-metabase-im-container-port-volume-1024x751.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-12-Container-Manager-container-metabase-im-container-port-volume-300x220.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-12-Container-Manager-container-metabase-im-container-port-volume-768x563.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-12-Container-Manager-container-metabase-im-container-port-volume.png 1219w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 12 &#8211; Container Manager &#8211; container metabase im container &#8211; port &#8211; volume</figcaption></figure>



<ol start="3" class="wp-block-list">
<li>Umgebungsvariable&nbsp;<code>GIT_COMMIT_SHA</code>:&nbsp;<code>unknown</code>&nbsp;eintragen</li>
</ol>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400857f1c&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400857f1c" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="751" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-13-Container-Manager-container-metabase-im-container-GIT_COMMIT_SHA-1024x751.png" alt="BILD 13 - Container Manager - container metabase im container - GIT_COMMIT_SHA" class="wp-image-830" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-13-Container-Manager-container-metabase-im-container-GIT_COMMIT_SHA-1024x751.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-13-Container-Manager-container-metabase-im-container-GIT_COMMIT_SHA-300x220.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-13-Container-Manager-container-metabase-im-container-GIT_COMMIT_SHA-768x564.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-13-Container-Manager-container-metabase-im-container-GIT_COMMIT_SHA.png 1221w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 13 &#8211; Container Manager &#8211; container metabase im container &#8211; GIT_COMMIT_SHA</figcaption></figure>



<ol start="4" class="wp-block-list">
<li>Container starten</li>
</ol>



<p><strong>Wichtig:</strong>&nbsp;Falls die Firewall auf deiner Diskstation aktiv ist, lege eine Regel für Port 3000 (Protokoll TCP) an – sonst kommst du über den Browser nicht auf Metabase.</p>



<p>Metabase läuft unter&nbsp;<code>http://</code>&nbsp;(nicht&nbsp;<code>https://</code>). Öffne&nbsp;<code>http://&lt;deine-Synology-IP&gt;:3000</code>&nbsp;im Browser. Beim ersten Start führt dich ein Setup durch die Datenbankverbindung:</p>



<ol class="wp-block-list">
<li><strong>Database type:</strong>&nbsp;PostgreSQL</li>



<li><strong>Display name:</strong>&nbsp;z. B. „KI News Datenbank&#8220;</li>



<li><strong>Host:</strong>&nbsp;Containername deiner Postgres-Instanz (z. B.&nbsp;<code>n8n_db</code>)</li>



<li><strong>Port:</strong>&nbsp;<code>5432</code></li>



<li><strong>Database name:</strong>&nbsp;<code>postgres</code></li>



<li><strong>Username:</strong>&nbsp;dein Postgres-Benutzername</li>



<li><strong>Password:</strong>&nbsp;dein Postgres-Passwort</li>
</ol>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440085872a&quot;}" data-wp-interactive="core/image" data-wp-key="69e440085872a" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="617" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-14-metabase-Startbildschirm-1024x617.png" alt="BILD 14 - metabase Startbildschirm" class="wp-image-831" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-14-metabase-Startbildschirm-1024x617.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-14-metabase-Startbildschirm-300x181.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-14-metabase-Startbildschirm-768x462.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-14-metabase-Startbildschirm-1536x925.png 1536w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-14-metabase-Startbildschirm.png 1586w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 14 &#8211; metabase Startbildschirm</figcaption></figure>



<p>Deine erste SQL-Auswertung erstellst du über&nbsp;<strong>+ NEU</strong>&nbsp;-&gt;&nbsp;<strong>&gt;_ SQL-Abfrage</strong>. Diese Query gibt dir einen ersten Tagesüberblick:</p>



<pre class="wp-block-code"><code>SELECT 
    DATE(created_at) AS datum,
    -- 1) Wie viele RSS-Feeds wurden eingelesen?
    COUNT(*) AS eingelesen_gesamt,
    -- 2) Wie viele davon wurden bewertet?
    COUNT(*) FILTER (WHERE status = 'bewertet') AS bewertet,
    -- 3) Verteilung der Scores (Umwandlung in Zahlenwert mit ::float)
    COUNT(*) FILTER (WHERE score_gesamt::float BETWEEN 0 AND 2.9) AS "Score_0_bis_2",
    COUNT(*) FILTER (WHERE score_gesamt::float BETWEEN 3 AND 7.9) AS "Score_3_bis_7",
    COUNT(*) FILTER (WHERE score_gesamt::float &gt;= 8) AS "Score_8_bis_10"
FROM ki_artikel
GROUP BY DATE(created_at)
ORDER BY datum DESC;</code></pre>



<h3 class="wp-block-heading">3.5 Agent 3: Content-Recherche</h3>



<p><strong>Ulf</strong>: „Wir haben jetzt bewertete Artikel, was kommt jetzt?&#8220;<br><strong>Tanja</strong>: „Jetzt wird es interessant, Agent 3 nimmt die besten Artikel – die mit Score 7,5 oder höher &#8211; und recherchiert dazu. Er lädt den Originaltext, sucht verwandte Quellen im Web und lässt GPT-4o-mini daraus einen strukturierten Hintergrundtext schreiben.&#8220;<br><strong>Ulf</strong>: „Moment, kann die KI nicht einfach selbst im Internet suchen? Warum der Umweg über Tavily?&#8220;<br><strong>Tanja</strong>: „Gute Frage. Schauen wir uns das an.&#8220;</p>



<h4 class="wp-block-heading">3.5.1 Den Workflow starten</h4>



<ol class="wp-block-list">
<li>Gehe zurück zur Workflow-Übersicht und klicke auf&nbsp;<strong>Create new workflow</strong></li>



<li>Nenne ihn oben links:&nbsp;<code>A3 Agent: Content-Recherche</code></li>



<li>Füge einen&nbsp;<strong>Schedule Trigger</strong>&nbsp;hinzu:
<ul class="wp-block-list">
<li>Trigger Interval: Hours</li>



<li>Stelle zunächst auf&nbsp;<strong>Manual</strong>&nbsp;zum Testen</li>



<li>Hours Between Triggers:&nbsp;<strong>23</strong></li>



<li>Trigger at Minute:</li>
</ul>
</li>
</ol>



<h4 class="wp-block-heading">3.5.2 Datensatz aus Datenbank auslesen</h4>



<ol class="wp-block-list">
<li>Füge eine&nbsp;<strong>Postgres-Node</strong>&nbsp;hinzu:
<ul class="wp-block-list">
<li>Node: Execute a SQL query</li>



<li>Credential to connect with:&nbsp;<code>n8n-postgres</code></li>



<li>Query:</li>
</ul>
</li>
</ol>



<pre class="wp-block-code"><code>SELECT a.id, a.url, a.title, a.description
FROM ki_artikel a
LEFT JOIN ki_story s ON s.primary_artikel_id = a.id
WHERE a.score_gesamt &gt;= 7.5
  AND s.id IS NULL
  AND (a.status IS NULL OR a.status &lt;&gt; 'ANGEREICHERT')
LIMIT 5;</code></pre>



<p><em>Hinweis:</em> Wir holen nur Artikel mit einem Gesamtscore von mindestens&nbsp;7.5&nbsp;– das sind die wirklich relevanten Treffer, die eine aufwendige Recherche wert sind. Das&nbsp;<code>LIMIT 5</code>&nbsp;hält die Laufzeit beim ersten Testen überschaubar.</p>



<p>Der&nbsp;<code>LEFT JOIN</code>&nbsp;mit&nbsp;<code>WHERE s.id IS NULL</code>&nbsp;ist eine elegante Abkürzung: Er findet alle Artikel, zu denen es noch keine Story gibt – also genau die, die noch bearbeitet werden müssen.</p>



<p>Führe außerdem diese zwei Index-Befehle einmalig direkt in der Datenbank aus, um sie abzusichern:</p>



<pre class="wp-block-code"><code>CREATE UNIQUE INDEX IF NOT EXISTS ki_story_primary_uniq ON ki_story(primary_artikel_id);</code></pre>



<p>und</p>



<pre class="wp-block-code"><code>CREATE&amp;nbsp;UNIQUE&amp;nbsp;INDEX IF NOT EXISTS idx_ki_artikel_url_normalized ON ki_artikel(url_normalized);</code></pre>



<h4 class="wp-block-heading">3.5.3 Loop einbauen</h4>



<p>Damit n8n jeden Artikel einzeln abarbeitet, kommt als nächstes der Loop-Knoten:</p>



<ul class="wp-block-list">
<li>Node:&nbsp;<strong>Loop Over Items (Split In Batches)</strong></li>



<li>Batch Size: 1</li>



<li>Knoten-Ausgang Done: bleibt leer</li>



<li>Konten-Ausgang Loop: nächster Knoten</li>
</ul>



<h4 class="wp-block-heading">3.5.4 Website-Inhalt abrufen</h4>



<p>Wir versuchen zunächst, den Volltext direkt von der Quellwebsite zu laden – als würde ein Mensch den Artikel öffnen und lesen.</p>



<ol class="wp-block-list">
<li>Füge einen&nbsp;<strong>HTTP Request-Node</strong>&nbsp;hinzu:
<ul class="wp-block-list">
<li>Method: GET</li>



<li>URL:&nbsp;<code>={{ $json.url }}</code></li>



<li>Add Options → Response Format:&nbsp;<strong>Text</strong></li>



<li>Send Headers:&nbsp;<strong>ON</strong></li>
</ul>
</li>
</ol>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Header Name</th><th>Value</th></tr></thead><tbody><tr><td>User-Agent</td><td><code>Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36</code></td></tr><tr><td>Accept</td><td><code>text/html</code></td></tr><tr><td>Accept-Language</td><td><code>de-DE,de;q=0.9,en;q=0.8</code></td></tr></tbody></table></figure>



<p>Diese Header sind wichtig: Viele Websites liefern schönere Inhalte, wenn die Anfrage wie ein echter Browser-Aufruf aussieht – statt wie ein nackter Bot.</p>



<ol start="2" class="wp-block-list">
<li>Füge einen&nbsp;<strong>Code Node (JavaScript)</strong>&nbsp;hinzu, der das rohe HTML in brauchbaren Fließtext verwandelt:</li>
</ol>



<pre class="wp-block-code"><code>// n8n Code node (JavaScript)
// Erwartet HTML im Feld: $json.data (aus HTTP Request)

const html = ($json.data || '').toString();

// 1) Skripte/Styles entfernen
let cleaned = html
  .replace(/&lt;script\b&#91;^&lt;]*(?:(?!&lt;\/script&gt;)&lt;&#91;^&lt;]*)*&lt;\/script&gt;/gi, ' ')
  .replace(/&lt;style\b&#91;^&lt;]*(?:(?!&lt;\/style&gt;)&lt;&#91;^&lt;]*)*&lt;\/style&gt;/gi, ' ');

// 2) Häufige Layout-Blöcke grob entfernen (optional, aber hilfreich)
cleaned = cleaned
  .replace(/&lt;nav\b&#91;^&lt;]*(?:(?!&lt;\/nav&gt;)&lt;&#91;^&lt;]*)*&lt;\/nav&gt;/gi, ' ')
  .replace(/&lt;header\b&#91;^&lt;]*(?:(?!&lt;\/header&gt;)&lt;&#91;^&lt;]*)*&lt;\/header&gt;/gi, ' ')
  .replace(/&lt;footer\b&#91;^&lt;]*(?:(?!&lt;\/footer&gt;)&lt;&#91;^&lt;]*)*&lt;\/footer&gt;/gi, ' ');

// 3) HTML-Tags -&gt; Text (mit Zeilenumbrüchen an sinnvollen Stellen)
cleaned = cleaned
  .replace(/&lt;\/(p|div|br|li|h1|h2|h3|h4|h5|section|article)&gt;/gi, '\n')
  .replace(/&lt;&#91;^&gt;]+&gt;/g, ' ');

// 4) HTML Entities (minimal)
cleaned = cleaned
  .replace(/&amp;nbsp;/g, ' ')
  .replace(/&amp;amp;/g, '&amp;')
  .replace(/&amp;quot;/g, '"')
  .replace(/&amp;#39;/g, "'")
  .replace(/&amp;lt;/g, '&lt;')
  .replace(/&amp;gt;/g, '&gt;');

// 5) Whitespace normalisieren
cleaned = cleaned
  .replace(/\r/g, '')
  .replace(/&#91; \t]+/g, ' ')
  .replace(/\n{3,}/g, '\n\n')
  .trim();

// 6) Optional: begrenzen (für DB/LLM)
const maxLen = 20000;
const content_candidate = cleaned.slice(0, maxLen);
const content_candidate_len = content_candidate.length;

// --- Qualitäts-Check ---
const words = content_candidate.split(/\s+/).filter(w =&gt; w.length &gt; 3);
const wordCount = words.length;

const avgWordLength =
  words.reduce((sum, w) =&gt; sum + w.length, 0) / (wordCount || 1);

const badMarkers = &#91;
  'cookie', 'zustimmen', 'abo', 'newsletter', 'anzeigen',
  'karriere', 'impressum', 'datenschutz', 'suche', 'login',
  'heise+', 'jobs'
];

const badHits = badMarkers.filter(m =&gt;
  content_candidate.toLowerCase().includes(m)
).length;

const content_quality_ok =
  content_candidate_len &gt; 1500 &amp;&amp;
  wordCount &gt; 250 &amp;&amp;
  avgWordLength &gt; 4 &amp;&amp;
  badHits &lt; 5;

return &#91;{
  ...$json,
  content_candidate,
  content_candidate_len,
  content_quality_ok,
  content_word_count: wordCount,
  content_avg_word_len: avgWordLength,
  content_bad_hits: badHits,
}];</code></pre>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e44008595f9&quot;}" data-wp-interactive="core/image" data-wp-key="69e44008595f9" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="728" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-15-n8n-Code-in-JavaScript-HTML-in-Fliesstext-umwandeln-1024x728.png" alt="BILD 15 - n8n - Code in JavaScript - HTML in Fließtext umwandeln" class="wp-image-833" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-15-n8n-Code-in-JavaScript-HTML-in-Fliesstext-umwandeln-1024x728.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-15-n8n-Code-in-JavaScript-HTML-in-Fliesstext-umwandeln-300x213.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-15-n8n-Code-in-JavaScript-HTML-in-Fliesstext-umwandeln-768x546.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-15-n8n-Code-in-JavaScript-HTML-in-Fliesstext-umwandeln-1536x1092.png 1536w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-15-n8n-Code-in-JavaScript-HTML-in-Fliesstext-umwandeln.png 1545w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 15 &#8211; n8n &#8211; Code in JavaScript &#8211; HTML in Fließtext umwandeln</figcaption></figure>



<p>Das Ergebnis enthält das Flag&nbsp;<code>content_quality_ok</code>. Ein brauchbarer Text braucht mindestens 1.500 Zeichen, 250 Wörter und darf nicht von Boilerplate-Begriffen wie „Cookie&#8220; oder „Impressum&#8220; dominiert sein. Das Flag dient als Metainformation; die Tavily-Recherche läuft in jedem Fall danach – der Web-Kontext ist die eigentliche Basis für den LLM-Text.</p>



<h4 class="wp-block-heading">3.5.5 Warum Tavily statt OpenAI-Websuche?</h4>



<p><strong>Ulf</strong>: „Kurze Frage, kann ich nicht einfach GPT mit Internetzugang nehmen? Dann brauche ich Tavily gar nicht.&#8220;<br><strong>Tanja</strong>: „Du kannst, aber schau dir kurz die Kosten an.&#8220;</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Feature</th><th>Basic LLM Chain</th><th>AI Agent + Tavily</th><th>AI Agent + Serper/Brave</th><th>OpenAI Search-Preview</th></tr></thead><tbody><tr><td>Internetzugriff</td><td>Nein</td><td>Ja (inkl. Textauszüge)</td><td>Ja (nur Links)</td><td>Ja (integriert)</td></tr><tr><td>Kosten pro Suche</td><td>&#8211;</td><td>0 Cent (bis 1.000/Monat kostenlos)</td><td>0,1 &#8211; 1,5 Cent</td><td>3 &#8211; 10 Cent</td></tr><tr><td>Ergebnis-Qualität</td><td>Nur wenn manuell gefüttert</td><td>Sehr gut – Inhalt bereits aufbereitet</td><td>Gut &#8211; Rohlinks, kein Textinhalt</td><td>Sehr gut</td></tr><tr><td>Kontrolle</td><td>Voll</td><td>Voll</td><td>Voll</td><td>Begrenzt</td></tr><tr><td>Setup-Aufwand</td><td>Minimal</td><td>Gering (1 API Key)</td><td>Gering (1 API Key)</td><td>Minimal</td></tr></tbody></table></figure>



<p><strong>Ulf:</strong> „Okay, ich versteh das noch nicht ganz,&#8220; und zeigt auf die Tabelle. „Serper und Brave liefern auch Suchergebnisse. Warum ist Tavily besser?&#8220;<br><strong>Tanja</strong>: „Stell dir vor, du schickst einen Praktikanten los, um Informationen über ein Thema zu sammeln. Serper und Brave kommen zurück mit einem Stapel Zeitungsadressen. Tavily kommt zurück mit den ausgeschnittenen Artikeln. Bereits lesbar, bereits sortiert.&#8220;<br><strong>Ulf</strong> runzelt die Stirn. „Also liefert Tavily den Inhalt der Seiten gleich mit?&#8220;<br><strong>Tanja</strong>: „Genau. Serper und Brave geben dir nur Links – du musst jede Seite noch selbst aufrufen und den Text extrahieren. Tavily liefert bereits aufbereitete Textauszüge. GPT-4o-mini bekommt also sauberen Kontext statt rohem HTML-Müll. Das spart Token – und bessere Eingabe bedeutet bessere Ausgabe.&#8220;<br><strong>Bernd</strong>: „Klingt nach wenig Unterschied, ich würde einfach OpenAIs eingebaute Websuche nehmen. Weniger Gedöns.&#8220;<br><strong>Tanja</strong>: „Kostet dich 3 bis 10 Cent pro Suche, Tavily ist bis tausend Suchen im Monat kostenlos. Danach 1,5 Cent. Das ist Faktor 10 bis 30 günstiger, bei gleicher oder besserer Qualität für unseren Anwendungsfall.&#8220;<br><strong>Ulf</strong>: „Tausend Suchen reichen uns?&#8220;<br><strong>Tanja</strong>: „Wir recherchieren täglich für maximal einen Artikel, mit bis zu 20 Tavily-Treffern pro Durchlauf. Das sind rund 600 Suchen im Monat. Passt locker ins kostenlose Kontingent.&#8220;<br><strong>Bernd</strong> tippt kurz auf seinem Handy. „Okay, Tavily.&#8220;<br><strong>Tanja</strong>: „Danke&#8220;.</p>



<h4 class="wp-block-heading">3.5.6 Tavily Search einrichten</h4>



<ol class="wp-block-list">
<li>Erstelle dir einen Account auf&nbsp;<a href="https://app.tavily.com/" target="_blank" rel="noopener">app.tavily.com</a>&nbsp;und kopiere deinen API Key</li>



<li>Füge in n8n den Node&nbsp;<strong>Search: Tavily</strong>&nbsp;hinzu</li>



<li>Erstelle unter&nbsp;<strong>Credential to connect with</strong>&nbsp;ein neues Credential mit deinem API Key</li>



<li>Konfiguriere den Node:
<ul class="wp-block-list">
<li>Query:</li>
</ul>
</li>
</ol>



<pre class="wp-block-code"><code>   {{ 
  (
    ($('Execute a SQL query').item.json.title || '') + ' ' + 
    ($('Execute a SQL query').item.json.description || '')
  ).slice(0, 380)
}}</code></pre>



<ol start="4" class="wp-block-list">
<li>Konfiguriere den Node:
<ul class="wp-block-list">
<li>Add Options → Search Depth: <strong>Advanced</strong>&nbsp;</li>



<li>Add Options → Max Results: <strong>20</strong></li>
</ul>
</li>
</ol>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400859f34&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400859f34" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="730" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-16-n8n-Search-Tavily-Parameter-Settings-1024x730.png" alt="BILD 16 - n8n - Search Tavily - Parameter Settings" class="wp-image-835" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-16-n8n-Search-Tavily-Parameter-Settings-1024x730.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-16-n8n-Search-Tavily-Parameter-Settings-300x214.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-16-n8n-Search-Tavily-Parameter-Settings-768x547.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-16-n8n-Search-Tavily-Parameter-Settings-1536x1095.png 1536w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-16-n8n-Search-Tavily-Parameter-Settings.png 1546w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 16 &#8211; n8n &#8211; Search Tavily &#8211; Parameter Settings</figcaption></figure>



<p>Die Query kombiniert Titel und Beschreibung des Artikels und schneidet bei 380 Zeichen ab. Mit&nbsp;<code>Advanced</code>&nbsp;und 20 Ergebnissen holen wir das Maximum aus dem Tavily-Free-Kontingent.</p>



<h4 class="wp-block-heading">3.5.7 Schlechte URLs aussortieren</h4>



<p>Tavily liefert manchmal SEO-Schrottseiten, Feed-Aggregatoren oder themenfremd. Ein Code-Node filtert diese heraus, bevor sie die Datenbank verschmutzen:</p>



<ul class="wp-block-list">
<li>Node:&nbsp;<strong>Code (JavaScript)</strong></li>



<li>Mode: Run Once for All Items</li>
</ul>



<pre class="wp-block-code"><code>const input = $input.first().json;
const list = Array.isArray(input.results) ? input.results : &#91;];

// --- Konfiguration ---
const BLOCKED_DOMAINS = &#91;
  'feed-reader.net', 'rssingn.com', 'finanztrends.de',
  'it-daily.net', 'possible.fm', 'edu.ly',
];

const BAD_TITLE_PATTERNS = &#91;
  'die besten', 'tools im vergleich', 'im vergleich', 'ranking', 'best of',
];

const MIN_CONTENT_LENGTH = 250;
const MIN_SCORE = 0.55;

function host(u) {
  try { return new URL(u).hostname.replace(/^www\./, ''); } catch { return ''; }
}

const kept = &#91;];
for (const r of list) {
  const url = String(r.url || '').toLowerCase();
  const title = String(r.title || '').toLowerCase();
  const content = String(r.content || '').toLowerCase();
  const h = host(url);

  let reason = null;
  if (!url || !title) reason = 'missing url/title';
  else if (BLOCKED_DOMAINS.some(d =&gt; h.includes(d))) reason = 'blocked domain';
  else if (BAD_TITLE_PATTERNS.some(p =&gt; title.includes(p))) reason = 'seo/list title';
  else if (content.length &lt; MIN_CONTENT_LENGTH) reason = 'too short content';
  else if (typeof r.score === 'number' &amp;&amp; r.score &lt; MIN_SCORE) reason = 'low score';

  if (!reason) kept.push({ ...r, _quality_flag: 'accepted' });
}

// Fallback: wenn alles rausfliegt, nimm Top 5 nach Score
const final = kept.length &gt; 0
  ? kept
  : &#91;...list].sort((a, b) =&gt; (b.score ?? 0) - (a.score ?? 0)).slice(0, 5)
      .map(r =&gt; ({ ...r, _quality_flag: 'fallback' }));

return final.map(r =&gt; ({
  json: {
    ...r,
    _debug: {
      input_count: list.length,
      kept_count: kept.length,
    }
  }
}));</code></pre>



<p>Der Fallback am Ende ist wichtig: Wenn alle Treffer rausgefiltert würden, nimmt der Code trotzdem die Top 5 nach Score – damit der Workflow nie komplett leer weiterläuft.</p>



<h4 class="wp-block-heading">3.5.8 Tavily-Treffer in der Datenbank speichern</h4>



<p>Die gefundenen Quellen werden doppelt verwertet: als Kontext für das LLM (nächster Schritt) und als eigene Datensätze in der Datenbank. Dafür brauchen wir drei Nodes hintereinander.</p>



<p><strong>Node 1: Prepare Tavily Results (Code in JavaScript)</strong><br>Dieser Code normalisiert die URLs der Tavily-Treffer und bereitet die Felder für die Datenbank vor &#8211; analog zur URL-Normalisierung aus Agent 1:</p>



<pre class="wp-block-code"><code>function normalizeUrl(input) {
  try {
    const url = new URL(input.startsWith('http') ? input : 'https://' + input);
    url.hash = '';
    const dropKeys = new Set(&#91;'fbclid','gclid','mc_cid','mc_eid','msclkid','utm_source']);
    for (const k of Array.from(url.searchParams.keys())) {
      if (k.toLowerCase().startsWith('utm_') || dropKeys.has(k.toLowerCase()))
        url.searchParams.delete(k);
    }
    url.hostname = url.hostname.replace(/^www\./i, '').toLowerCase();
    url.protocol = 'https:';
    if (url.pathname === '/') url.pathname = '';
    return url.toString();
  } catch (e) { return input; }
}

function extractHost(input) {
  try { return new URL(input).hostname.replace(/^www\./i, '').toLowerCase(); }
  catch (e) { return 'unknown'; }
}

const fromId = $('Execute a SQL query').item?.json?.id ?? null;
const results = items.every(it =&gt; typeof it?.json?.url === 'string')
  ? items.map(it =&gt; it.json)
  : (Array.isArray(items?.&#91;0]?.json?.results) ? items&#91;0].json.results : &#91;]);

return results.filter(r =&gt; r?.url).slice(0, 10).map((r, idx) =&gt; {
  const norm = normalizeUrl(r.url);
  const host = extractHost(norm || r.url);
  return { json: {
    from_artikel_id: fromId,
    relation_type: 'tavily_related',
    query: items?.&#91;0]?.json?.query ?? '',
    rank: idx + 1,
    score: r.score ?? null,
    url: r.url,
    url_normalized: norm,
    title: r.title ?? '(no title)',
    description: (r.content ?? '').slice(0, 800),
    source: host,
    source_type: 'tavily',
  }};
});</code></pre>



<p><strong>Node 2: Upsert Tavily Article (Postgres – Execute a SQL query)</strong><br>Jeder gefundene Treffer landet als eigener Datensatz in&nbsp;<code>ki_artikel</code>. Durch&nbsp;<code>ON CONFLICT</code>&nbsp;wird ein bereits bekannter Artikel nicht doppelt eingetragen, sondern nur fehlende Felder ergänzt:</p>



<pre class="wp-block-code"><code>INSERT INTO ki_artikel (
  url, url_normalized, title, description,
  source, published_date, image_url, source_type, status, first_seen_at
)
VALUES (
  '{{ ($json.url || "").replace(/'/g, "''") }}',
  '{{ ($json.url_normalized || "").replace(/'/g, "''") }}',
  '{{ ($json.title || "").replace(/'/g, "''") }}',
  '{{ ($json.description || "").replace(/'/g, "''") }}',
  '{{ ($json.source || "").replace(/'/g, "''") }}',
  NULL, NULL, 'tavily', 'ANGEREICHERT', now()
)
ON CONFLICT (url_normalized)
DO UPDATE SET
  title       = COALESCE(NULLIF(ki_artikel.title,''), EXCLUDED.title),
  description = COALESCE(NULLIF(ki_artikel.description,''), EXCLUDED.description),
  source      = COALESCE(NULLIF(ki_artikel.source,''), EXCLUDED.source),
  status      = COALESCE(NULLIF(ki_artikel.status,''), 'ANGEREICHERT')
RETURNING id;</code></pre>



<p><strong>Node 3: Upsert Tavily Edge (Postgres &#8211; Execute a SQL query)</strong><br>Die Verbindung zwischen dem Ausgangsartikel und dem gefundenen Tavily-Treffer wird in&nbsp;<code>ki_artikel_edges</code>&nbsp;gesichert:</p>



<pre class="wp-block-code"><code>INSERT INTO ki_artikel_edges (
  from_artikel_id, to_artikel_id, relation_type, query, rank, score, retrieved_at
)
VALUES (
  {{ $node&#91;"Prepare Tavily Results"].json.from_artikel_id }},
  {{ $node&#91;"Upsert Tavily Article"].json.id }},
  '{{ (($node&#91;"Prepare Tavily Results"].json.relation_type) || "tavily_related").replace(/'/g, "''") }}',
  '{{ (($node&#91;"Prepare Tavily Results"].json.query) || "").replace(/'/g, "''") }}',
  {{ $node&#91;"Prepare Tavily Results"].json.rank || 1 }},
  {{ $node&#91;"Prepare Tavily Results"].json.score ?? 'NULL' }},
  now()
)
ON CONFLICT (from_artikel_id, to_artikel_id, relation_type)
DO UPDATE SET
  rank         = EXCLUDED.rank,
  score        = EXCLUDED.score,
  query        = EXCLUDED.query,
  retrieved_at = now();</code></pre>



<h4 class="wp-block-heading">3.5.9 LLM-Kontext aufbereiten</h4>



<p>Parallel zur Datenbankspeicherung bereitet ein&nbsp;<strong>Edit Fields-Node</strong>&nbsp;den kombinierten Kontext für GPT-4o-mini auf:</p>



<ul class="wp-block-list">
<li>Node:&nbsp;<strong>Edit Fields</strong></li>



<li>Field Name:&nbsp;<code>llm_context</code></li>



<li>Type: String</li>



<li>Value (Expression):</li>
</ul>



<pre class="wp-block-code"><code>=RSS ARTICLE
Title: {{ $('Loop Over Items').item.json.title }}
Description: {{ $('Loop Over Items').item.json.description }}

WEB SEARCH CONTEXT
={{
  "RSS ARTICLE\nTitle: " + 
  $('Loop Over Items').item.json.title + 
  "\nDescription: " + 
  $('Loop Over Items').item.json.description +
  "\n\nWEB SEARCH CONTEXT\n" + 
  ($node&#91;"Search: Tavily"].json.results || &#91;])
    .slice(0, 10)
    .map((r, i) =&gt; "&#91;Source " + (i+1) + "]\n" + (r.content || ""))
    .join("\n\n")
}}</code></pre>



<p>Damit hat die KI sowohl den Original-RSS-Artikel als auch bis zu 10 aufbereitete Webseitentexte aus Tavily als Kontext.</p>



<h4 class="wp-block-heading">3.5.10 Hintergrundtext mit GPT-4o-mini erstellen</h4>



<ul class="wp-block-list">
<li>Node:&nbsp;<strong>Basic LLM Chain</strong></li>



<li>Source for Prompt: Define below</li>



<li>Prompt (User Message):</li>
</ul>



<pre class="wp-block-code"><code>Du erhältst einen Artikel aus einem RSS-Feed sowie zusätzlichen Web-Kontext.

Aufgabe:
- Beschreibe das Thema inhaltlich breiter und tiefer.
- Erkläre Hintergründe, technische Zusammenhänge und Einordnung.
- Struktur: 1) Kurzüberblick (3-4 Sätze) 2) Details (5-10 Bulletpoints) 3) Bedeutung/Implikationen (3 Bulletpoints).
- Keine Quellenangaben, keine Spekulationen.

TEXT:
{{ $json.llm_context }}</code></pre>



<p>Den Basic LLM Chain mit dem&nbsp;<strong>OpenAI Chat Model</strong>&nbsp;verbinden:</p>



<ul class="wp-block-list">
<li>Node: OpenAI Chat Model</li>



<li>Credential to connect with: OpenAI account</li>



<li>Model:&nbsp;<strong>gpt-4o-mini</strong></li>
</ul>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440085aac1&quot;}" data-wp-interactive="core/image" data-wp-key="69e440085aac1" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="727" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-17-n8n-Basic-LLM-Chain-Parameter-Settings-1024x727.png" alt="BILD 17 - n8n - Basic LLM Chain - Parameter Settings" class="wp-image-837" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-17-n8n-Basic-LLM-Chain-Parameter-Settings-1024x727.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-17-n8n-Basic-LLM-Chain-Parameter-Settings-300x213.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-17-n8n-Basic-LLM-Chain-Parameter-Settings-768x545.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-17-n8n-Basic-LLM-Chain-Parameter-Settings-1536x1091.png 1536w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-17-n8n-Basic-LLM-Chain-Parameter-Settings.png 1545w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 17 &#8211; n8n &#8211; Basic LLM Chain &#8211; Parameter Settings</figcaption></figure>



<h4 class="wp-block-heading">3.5.11 Story-Felder aufbereiten</h4>



<p>Ein&nbsp;<strong>Edit Fields-Node</strong>&nbsp;fasst das LLM-Ergebnis zusammen mit Metadaten aus dem Loop:</p>



<ul class="wp-block-list">
<li>Node:&nbsp;<strong>Edit Fields</strong>&nbsp;(Name:&nbsp;<code>Edit Fields: ki_story</code>)</li>
</ul>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Name</th><th>Type</th><th>Value</th></tr></thead><tbody><tr><td>id</td><td>Number</td><td><code>={{ $('Loop Over Items').item.json.id }}</code></td></tr><tr><td>content_enriched</td><td>String</td><td><code>={{ $json.text }}</code></td></tr><tr><td>enrichment_source</td><td>String</td><td><code>search_llm</code></td></tr><tr><td>tavily_link_count</td><td>String</td><td><code>={{ $items("Code in JavaScript: schlechte url aussortieren").length }}</code></td></tr><tr><td>score_gesamt_enriched</td><td>Number</td><td><code>={{ (Math.round(($('Loop Over Items').item.json.score_gesamt | 0) * 10) + ($items("Code in JavaScript: schlechte url aussortieren").length | 0)) / 10 }}</code></td></tr></tbody></table></figure>



<p>Der&nbsp;<code>score_gesamt_enriched</code>&nbsp;kombiniert den ursprünglichen Bewertungsscore mit der Anzahl brauchbarer Tavily-Quellen – je mehr gute Quellen gefunden wurden, desto höher steigt der Score leicht an.</p>



<h4 class="wp-block-heading">3.5.12 Story in Datenbank speichern</h4>



<ul class="wp-block-list">
<li>Node:&nbsp;<strong>Postgres – Execute a SQL query</strong>&nbsp;(Name:&nbsp;<code>Upsert Story (ki_story)</code>)</li>
</ul>



<pre class="wp-block-code"><code>INSERT INTO ki_story (
  primary_artikel_id,
  content_enriched,
  enrichment_source,
  tavily_link_count,
  score_gesamt_enriched,
  status,
  updated_at
)
VALUES (
  {{ $json.id }},
  '{{ ($json.content_enriched || "").replace(/'/g, "''") }}',
  '{{ ($json.enrichment_source || "").replace(/'/g, "''") }}',
  {{ parseFloat($json.tavily_link_count) || 0 }},
  {{ parseFloat($json.score_gesamt_enriched) || 0 }},
  'ANGEREICHERT',
  now()
)
ON CONFLICT (primary_artikel_id)
DO UPDATE SET
  content_enriched      = EXCLUDED.content_enriched,
  enrichment_source     = EXCLUDED.enrichment_source,
  tavily_link_count     = EXCLUDED.tavily_link_count,
  score_gesamt_enriched = EXCLUDED.score_gesamt_enriched,
  updated_at            = now();</code></pre>



<h4 class="wp-block-heading">3.5.13 Status aktualisieren und Loop schließen</h4>



<p>Zum Abschluss wird der Status des Artikels in&nbsp;<code>ki_artikel</code>&nbsp;auf&nbsp;<code>ANGEREICHERT</code>&nbsp;gesetzt, damit Agent 4 ihn im nächsten Schritt aufgreifen kann.</p>



<ol class="wp-block-list">
<li>Füge einen&nbsp;<strong>Postgres-Node</strong>&nbsp;hinzu:
<ul class="wp-block-list">
<li>Node: Update rows in a table</li>



<li>Credential to connect with:&nbsp;<code>n8n-postgres</code></li>



<li>Operation: Update</li>



<li>Schema: public</li>



<li>Table: ki_artikel</li>



<li>Mapping Column Mode: Map Each Column Manually</li>



<li>Columns to match on:&nbsp;<strong>id</strong></li>
</ul>
</li>
</ol>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Feld</th><th>Value</th></tr></thead><tbody><tr><td>id (using to match)</td><td><code>={{ $('Loop Over Items').item.json.id }}</code></td></tr><tr><td>status</td><td><code>ANGEREICHERT</code></td></tr></tbody></table></figure>



<ol start="2" class="wp-block-list">
<li>Verbinde den Ausgang dieses Nodes&nbsp;zurück mit dem Eingang von „Loop Over Items&#8220;, damit alle weiteren Artikel aus der Datenbank der Reihe nach abgearbeitet werden.</li>
</ol>



<h4 class="wp-block-heading">3.5.14 Workflow veröffentlichen</h4>



<p>Stelle den Schedule Trigger auf&nbsp;<strong>23 Stunden</strong>&nbsp;und aktiviere den Workflow über&nbsp;<strong>Publish</strong>. Agent 3 läuft damit einmal täglich, reichert alle Artikel mit&nbsp;<code>score_gesamt &gt;= 7.5</code>&nbsp;an und übergibt sie bereit an Agent 4.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440085b4cb&quot;}" data-wp-interactive="core/image" data-wp-key="69e440085b4cb" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="484" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-18-n8n-Fertiger-Workflow-3-Agent-Content-Recherche-1024x484.png" alt="BILD 18 - n8n - Fertiger Workflow - 3 Agent - Content-Recherche" class="wp-image-839" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-18-n8n-Fertiger-Workflow-3-Agent-Content-Recherche-1024x484.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-18-n8n-Fertiger-Workflow-3-Agent-Content-Recherche-300x142.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-18-n8n-Fertiger-Workflow-3-Agent-Content-Recherche-768x363.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-18-n8n-Fertiger-Workflow-3-Agent-Content-Recherche-1536x725.png 1536w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-18-n8n-Fertiger-Workflow-3-Agent-Content-Recherche.png 1842w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 18 &#8211; n8n &#8211; Fertiger Workflow &#8211; 3 Agent &#8211; Content-Recherche</figcaption></figure>



<h3 class="wp-block-heading">3.6 Agent 4: Artikel erstellen mit eigenem Bild</h3>



<p><strong>Ulf</strong>: „Jetzt wird es richtig spannend. Jetzt schreibt die KI den Artikel?&#8220;<br><strong>Tanja</strong>: „Claude schreibt ihn, und Flux-2-Flex malt dazu ein Coverbild.&#8220;<br><strong>Bernd</strong> schaut auf. „Ich habe meinen letzten Artikel einfach von einer anderen Website kopiert und ein bisschen umgeschrieben. Hat keiner gemerkt.&#8220;<br>Stille.<br><strong>Tanja</strong>: „Das, nennt sich Urheberrechtsverletzung.&#8220;<br><strong>Bernd</strong>: „Aber …&#8220;<br><strong>Tanja</strong>: „Nein.&#8220;</p>



<h4 class="wp-block-heading">3.6.1 Rechtliche Einschätzung</h4>



<p>Vorab eine kurze persönliche Einschätzung als Laie, das ist keine Rechtsberatung:<br><strong>Text:</strong>&nbsp;Die KI darf Fakten und Kontext verwenden, aber niemals Sätze aus dem Originalartikel wörtlich übernehmen. Kurze Zitate sind erlaubt, wenn sie als solche gekennzeichnet und mit Quellenlink versehen sind. Claude wird im Prompt explizit angewiesen, alles vollständig neu zu formulieren.<br><strong>Bilder:</strong>&nbsp;Das größte Abmahnrisiko liegt bei Bildern. Das&nbsp;<code>image_url</code>-Feld aus dem RSS-Feed darf&nbsp;<strong>nicht</strong>&nbsp;einfach als Featured Image übernommen werden – das wäre die Neuveröffentlichung eines urheberrechtlich geschützten Bildes auf deiner Website. Stattdessen generieren wir mit Flux-2-Flex ein eigenes Bild, das zu 100 % uns gehört.</p>



<h4 class="wp-block-heading">3.6.2 Den Workflow starten</h4>



<ol class="wp-block-list">
<li>Gehe zur Workflow-Übersicht und klicke auf&nbsp;<strong>Create new workflow</strong></li>



<li>Nenne ihn:&nbsp;<code>A4 Agent: Artikel erstellen mit eigenem Bild</code></li>



<li>Füge einen&nbsp;<strong>Schedule Trigger</strong>&nbsp;hinzu:
<ul class="wp-block-list">
<li>Trigger Interval: Hours</li>



<li>Hours Between Triggers:&nbsp;<strong>23</strong></li>



<li>Trigger at Minute: 0<br>Für den Aufbau nutzen wir zunächst den&nbsp;<strong>Manual Trigger</strong>, damit wir beim Testen direkt starten können.</li>
</ul>
</li>
</ol>



<h4 class="wp-block-heading">3.6.3 Die beste Story aus der Datenbank holen</h4>



<p>Agent 4 liest aus der&nbsp;<code>ki_story</code>-Tabelle – dort liegt der angereicherte Inhalt aus Agent 3. Das SQL-Query ist das komplexeste des gesamten Projekts: Es holt die beste Story und lädt direkt alle zugehörigen Tavily-URLs als Array mit, damit Claude sie im Quellenabschnitt verlinkt.</p>



<ol class="wp-block-list">
<li>Füge eine&nbsp;<strong>Postgres-Node</strong>&nbsp;hinzu:
<ul class="wp-block-list">
<li>Node: Execute a SQL query</li>



<li>Query:</li>
</ul>
</li>
</ol>



<pre class="wp-block-code"><code>SELECT
  s.id AS story_id,
  s.status,
  s.score_gesamt_enriched,
  s.content_enriched,

  a.title AS original_title,
  a.url AS original_url,
  a.published_date AS original_published_at,
  a.source AS original_source,

  COALESCE((
    SELECT ARRAY_AGG(x.url ORDER BY x.rank NULLS LAST, x.retrieved_at DESC, x.url)
    FROM (
      SELECT DISTINCT
        a2.url,
        e.rank,
        e.retrieved_at
      FROM ki_artikel_edges e
      JOIN ki_artikel a2
        ON a2.id = e.to_artikel_id
      WHERE e.from_artikel_id = s.primary_artikel_id
        AND e.relation_type = 'tavily_related'
        AND a2.url_normalized IS DISTINCT FROM a.url_normalized
      ORDER BY e.rank NULLS LAST, e.retrieved_at DESC, a2.url
      LIMIT 10
    ) x
  ), ARRAY&#91;]::text&#91;]) AS tavily_urls

FROM ki_story s
JOIN ki_artikel a ON a.id = s.primary_artikel_id
WHERE s.status = 'ANGEREICHERT'
ORDER BY s.score_gesamt_enriched DESC
LIMIT 1;</code></pre>



<h4 class="wp-block-heading">3.6.4 Artikel-Prompt für Claude aufbauen</h4>



<p>Ein&nbsp;<strong>Edit Fields-Node</strong>&nbsp;baut den vollständigen Prompt auf. Er ist bewusst restriktiv: sechs verbindliche Redaktionsregeln verhindern Urheberrechtsverletzungen.</p>



<ul class="wp-block-list">
<li>Node:&nbsp;<strong>Edit Fields</strong>&nbsp;(Name:&nbsp;<code>Edit Fields: Prompt erstellen</code>)</li>



<li>Add Field → Name:&nbsp;<code>`prompt`</code>&nbsp;→ Type: String → Value (Expression):</li>
</ul>



<pre class="wp-block-code"><code>={{ 
"Du bist Redakteur für foundic.org (Kategorie NEWS).\n\n" +

"REGELN (verbindlich):\n" +
"1) Du darfst Fakten verwenden, aber NICHTS wörtlich übernehmen. Alles vollständig neu formulieren.\n" +
"2) Keine Tabellen aus der Quelle übernehmen.\n" +
"3) Zitate: Standard 0. Nur wenn zwingend nötig: max. 1 Zitat &lt;20 Wörter.\n" +
"4) Keine erfundenen Details. Bei Unsicherheit vorsichtig/konjunktiv.\n" +
"5) ANTWORT: ausschließlich ein einziges, gültiges JSON-Objekt. Kein Text davor/danach. Kein Markdown. Keine ```.\n" +
"6) WICHTIG: In JSON-Strings dürfen KEINE echten Zeilenumbrüche vorkommen. Nutze ein Array für Content-Blöcke.\n\n" +

"ARTIKELDATEN:\n" +
"ORIGINAL_TITEL: " + ($json.title ?? "") + "\n" +
"BESCHREIBUNG: " + ($json.description ?? "") + "\n" +
"INHALT (nur Kontext, NICHT übernehmen): " + (($json.content ?? "").slice(0, 1500)) + "\n" +
"QUELLE: " + ($json.source ?? "") + "\n" +
"DATUM: " + ($json.published_date ?? "") + "\n" +
"URL: " + ($json.url ?? "") + "\n\n" +

"Pflichtregeln für wp_title:\n" +
"- wp_title ist eine kurze Umformulierung des ORIGINAL_TITEL (gleicher Sachverhalt).\n" +
"- wp_title enthält mindestens 2 Kernbegriffe aus ORIGINAL_TITEL (z.B. Siemens/CES/Industrie).\n" +
"- max. 12 Wörter.\n\n" +

"ERWARTETES JSON (Keys nie weglassen, fehlende Werte: \"\" oder &#91;]):\n" +
"{\n" +
"  \"wp_title\": \"...\",\n" +
"  \"wp_excerpt\": \"...\",\n" +
"  \"wp_content_blocks\": &#91;\n" +
"    \"&lt;h2&gt;Worum geht’s?&lt;/h2&gt;\",\n" +
"    \"&lt;p&gt;...&lt;/p&gt;\",\n" +
"    \"&lt;h2&gt;Hintergrund &amp; Einordnung&lt;/h2&gt;\",\n" +
"    \"&lt;p&gt;...&lt;/p&gt;\",\n" +
"    \"&lt;p&gt;...&lt;/p&gt;\",\n" +
"    \"&lt;h2&gt;Was bedeutet das?&lt;/h2&gt;\",\n" +
"    \"&lt;ul&gt;&lt;li&gt;...&lt;/li&gt;&lt;li&gt;...&lt;/li&gt;&lt;li&gt;...&lt;/li&gt;&lt;/ul&gt;\",\n" +
"    \"&lt;h2&gt;Quelle&lt;/h2&gt;\",\n" +
"    \"&lt;p&gt;&lt;a href=\\\"" + ($json.url ?? "") + "\\\"&gt;" + (($json.title ?? "").replace(/"/g, '\\"')) + "&lt;/a&gt; (" + ($json.source ?? "") + ", " + ($json.published_date ?? "") + ")&lt;/p&gt;\"\n" +
"  ],\n" +
"    \"&lt;p&gt;&lt;i&gt;Dieser Artikel wurde mit KI erstellt und basiert auf den angegebenen Quellen sowie den Trainingsdaten des Sprachmodells.&lt;/i&gt;&lt;/p&gt;\"\n" +  
" ],\n" +
"  \"wp_tags\": &#91;\"...\",\"...\",\"...\",\"...\",\"...\"]\n" +
"}\n"
}}</code></pre>



<p>Der Prompt ist bewusst restriktiv aufgebaut: sechs verbindliche Redaktionsregeln verhindern Urheberrechtsverletzungen, die Quellen-Regeln sorgen dafür, dass Claude nur hochwertige Medien verlinkt, und das JSON-Ausgabeformat ermöglicht die maschinelle Weiterverarbeitung ohne Nachbearbeitung.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440085beb1&quot;}" data-wp-interactive="core/image" data-wp-key="69e440085beb1" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="727" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-19-n8n-Edit-Fields-Prompt-erstellen-1024x727.png" alt="BILD 19 - n8n - Edit Fields - Prompt erstellen" class="wp-image-840" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-19-n8n-Edit-Fields-Prompt-erstellen-1024x727.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-19-n8n-Edit-Fields-Prompt-erstellen-300x213.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-19-n8n-Edit-Fields-Prompt-erstellen-768x545.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-19-n8n-Edit-Fields-Prompt-erstellen-1536x1090.png 1536w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-19-n8n-Edit-Fields-Prompt-erstellen.png 1540w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 19 &#8211; n8n &#8211; Edit Fields &#8211; Prompt erstellen</figcaption></figure>



<h4 class="wp-block-heading">3.6.5 Artikel mit Claude Sonnet schreiben</h4>



<ul class="wp-block-list">
<li>Node:&nbsp;<strong>Message a model</strong>&nbsp;(Anthropic)</li>



<li>Credential to connect with: Anthropic API Key (erstellen unter&nbsp;<a href="https://console.anthropic.com/" target="_blank" rel="noopener">console.anthropic.com</a>)</li>



<li>Model:&nbsp;<strong>claude-sonnet-4-5-20250929</strong></li>



<li>Messages → Content:&nbsp;<code>={{ $json['</code>prompt<code>'] }}</code></li>



<li>Options → Maximum Number of Tokens:&nbsp;<strong>4000</strong><br>Das Token-Limit auf 4000 hochzusetzen ist wichtig – ohne diese Einstellung wird der Artikel mittendrin abgeschnitten.</li>
</ul>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440085c4d6&quot;}" data-wp-interactive="core/image" data-wp-key="69e440085c4d6" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="728" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-20-n8n-Message-a-model-claude-sonnet-4-5-1024x728.png" alt="BILD 20 - n8n - Message a model - claude sonnet 4-5" class="wp-image-842" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-20-n8n-Message-a-model-claude-sonnet-4-5-1024x728.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-20-n8n-Message-a-model-claude-sonnet-4-5-300x213.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-20-n8n-Message-a-model-claude-sonnet-4-5-768x546.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-20-n8n-Message-a-model-claude-sonnet-4-5-1536x1092.png 1536w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-20-n8n-Message-a-model-claude-sonnet-4-5.png 1544w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 20 &#8211; n8n &#8211; Message a model &#8211; claude sonnet 4-5</figcaption></figure>



<h4 class="wp-block-heading">3.6.6 Claude-Output parsen</h4>



<p>Claude liefert die Antwort als Rohtext zurück. Ein&nbsp;<strong>Edit Fields-Node</strong>&nbsp;extrahiert daraus das JSON-Objekt:</p>



<ul class="wp-block-list">
<li>Node:&nbsp;<strong>Edit Fields</strong>&nbsp;(Name:&nbsp;<code>Edit Fields1</code>)</li>



<li>Add Field -&gt; Name:&nbsp;<code>parsed</code>&nbsp;-&gt; Type: Object -&gt; Value:</li>
</ul>



<pre class="wp-block-code"><code>={{
  (() =&gt; {
    const raw =
      $json?.content?.&#91;0]?.text ??
      $json?.content?.&#91;0]?.content?.&#91;0]?.text ??
      $json?.text ??
      "";

    const cleaned = raw.replace(/```(?:json)?/gi, "").trim();

    try {
      return JSON.parse(cleaned);
    } catch (e) {
      return { error: "JSON konnte nicht gelesen werden", raw: cleaned };
    }
  })()
}}</code></pre>



<p>Der Code probiert mehrere mögliche Pfade im Claude-Response-Objekt durch. Falls das Parsing scheitert, gibt er ein Fehlerobjekt zurück – so bricht der Workflow nicht kommentarlos ab, sondern hinterlässt einen lesbaren Hinweis.</p>



<h4 class="wp-block-heading">3.6.7 Felder für WordPress aufbereiten</h4>



<p>Ein zweiter&nbsp;<strong>Edit Fields-Node</strong>&nbsp;„entpackt&#8220; die geparsten Felder in eigenständige, benannte Variablen:</p>



<ul class="wp-block-list">
<li>Node:&nbsp;<strong>Edit Fields</strong>&nbsp;(Name:&nbsp;<code>Edit Fields2</code>)</li>
</ul>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Name</th><th>Type</th><th>Value</th></tr></thead><tbody><tr><td>wp_title</td><td>String</td><td><code>={{ $json.parsed.wp_title }}</code></td></tr><tr><td>wp_content</td><td>String</td><td><code>={{ $json.parsed.wp_content_blocks.join('\n\n') }}</code></td></tr><tr><td>wp_excerpt</td><td>String</td><td><code>={{ $json.parsed.wp_excerpt }}</code></td></tr><tr><td>wp_tags</td><td>String</td><td><code>={{ $json.parsed.wp_tags }}</code></td></tr></tbody></table></figure>



<p>Die&nbsp;<code>wp_content_blocks</code>&nbsp;werden durch&nbsp;<code>join('\n\n')</code>&nbsp;zu einem einzigen HTML-String zusammengefügt – genau das Format, das die WordPress REST API erwartet.</p>



<h4 class="wp-block-heading">3.6.8 Bildprompt für Flux aufbauen</h4>



<p>Jetzt startet der Bildgenerierungsprozess. Ein&nbsp;<strong>Edit Fields-Node</strong>&nbsp;baut den Flux-Prompt auf Basis des fertig geschriebenen Artikels:</p>



<ul class="wp-block-list">
<li>Node:&nbsp;<strong>Edit Fields</strong>&nbsp;(Name:&nbsp;<code>Edit Fields3</code>)</li>



<li>Add Field → Name:&nbsp;<code>`prompt`</code>&nbsp;→ Type: String → Value:</li>
</ul>



<pre class="wp-block-code"><code>={{ 
"THEMA (kurz): " + ($json.wp_title ?? "") + 
". KONTEXT (kurz): " + ($json.wp_excerpt ?? "") + 
". " +
"Erstelle auf Basis des obigen Blogtextes eine moderne, vektorbasierte Editorial-Illustration im Flat-Design, geeignet als ruhiges Coverbild für einen professionellen Tech- oder Wissensblog. " +
"Stil und Gestaltung: Editorial-Flat-Illustration (Flat Design 2.0), vektorbasiert, sauber und minimalistisch. " +
"Klare Linien, einfache geometrische Formen, ruhige Flaechen und harmonische Proportionen. " +
"Reduzierte, professionelle Farbpalette mit warmen, gedämpften Toenen (Beige, Apricot, Orange) kombiniert mit zurueckhaltenden Blau- und Gruentoenen auf hellem Hintergrund. " +
"Weiches, flaechiges Licht mit sehr subtilen Schatten oder leichten Verlaeufen, keine realistische Lichtquelle. " +
"Abstrahierte, neutrale Figuren oder symbolische Objekte ohne individuelle Merkmale. " +
"Aufgeraeumte Komposition mit Fokus auf eine zentrale visuelle Metapher. " +
"Ruhige, sachliche Bildwirkung mit redaktionellem Charakter. " +
"Inhaltliche Vorgaben: Thema visuell abstrahieren, nicht woertlich oder erzählerisch. Keine konkrete Szene mit erkennbarem Ort oder realen Marken. " +
"Zwingende Verbote: Kein Text im Bild (keine Buchstaben, Woerter, Zahlen, Schriftzeichen). Keine Logos/Markenzeichen/firmenspezifischen Symbole. Keine Fotografie, kein Fotorealismus. Keine 3D-Darstellung. Keine Comic- oder Cartoon-Optik. " +
"Technische Vorgaben: Quadratisches Bildformat. Zeitgemaesser, konsistenter Stil fuer redaktionelle Online-Inhalte. "
}}</code></pre>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440085cd78&quot;}" data-wp-interactive="core/image" data-wp-key="69e440085cd78" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="727" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-21-n8n-Edit-Fields3-Bildprompt-fuer-Flux-2-Flex-1024x727.png" alt="BILD 21 - n8n - Edit Fields3 Bildprompt für Flux-2-Flex" class="wp-image-844" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-21-n8n-Edit-Fields3-Bildprompt-fuer-Flux-2-Flex-1024x727.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-21-n8n-Edit-Fields3-Bildprompt-fuer-Flux-2-Flex-300x213.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-21-n8n-Edit-Fields3-Bildprompt-fuer-Flux-2-Flex-768x545.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-21-n8n-Edit-Fields3-Bildprompt-fuer-Flux-2-Flex-1536x1090.png 1536w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-21-n8n-Edit-Fields3-Bildprompt-fuer-Flux-2-Flex.png 1539w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 21 &#8211; n8n &#8211; Edit Fields3 Bildprompt für Flux-2-Flex</figcaption></figure>



<p>Der Prompt nutzt&nbsp;<code>wp_title</code>&nbsp;und&nbsp;<code>wp_excerpt</code>&nbsp;aus dem gerade erstellten Artikel als inhaltliche Basis. Die detaillierten Stil-Vorgaben (Flat Design 2.0, gedämpfte Farben, kein Text, kein Fotorealismus) sorgen für ein konsistentes, redaktionelles Bildlook über alle generierten Cover hinweg.</p>



<h4 class="wp-block-heading">3.6.9 Bild bei Black Forest Labs anfordern</h4>



<p>Die BFL-API arbeitet asynchron – du stellst einen Auftrag, bekommst eine Auftragsnummer zurück und fragst später nach, ob das Bild fertig ist. Wie eine Bäckerei: Bestellung aufgeben, Zettelchen nehmen, später abholen.</p>



<p><strong>Schritt 1: API Key einrichten</strong><br>Erstelle auf&nbsp;<a href="https://bfl.ai/" target="_blank" rel="noopener">bfl.ai</a>&nbsp;einen Account, lade Guthaben auf und kopiere deinen API Key. Speichere ihn in n8n als Custom Auth Credential:</p>



<ul class="wp-block-list">
<li>Gehe zu&nbsp;<strong>n8n Hauptmenü → Credentials → New</strong></li>



<li>Type:&nbsp;<strong>Custom Auth</strong></li>



<li>Name: z. B.&nbsp;<code>BFL API Key</code></li>



<li>JSON:</li>
</ul>



<pre class="wp-block-code"><code>{
  "headers": {
    "x-key": "bfl_DEIN_API_KEY_HIER"
  }
}</code></pre>



<p><strong>Schritt 2: Bild-Job starten</strong></p>



<ul class="wp-block-list">
<li>Node:&nbsp;<strong>HTTP Request</strong>&nbsp;(Name:&nbsp;<code>HTTP Request - URL Bild</code>)</li>



<li>Method: POST</li>



<li>URL:&nbsp;<code>https://api.bfl.ai/v1/flux-2-flex</code></li>



<li>Authentication: Generic Credential Type → Custom Auth → dein BFL-Credential</li>



<li>Send Headers: ON
<ul class="wp-block-list">
<li>Name:&nbsp;<code>Content-Type</code>&nbsp;/ Value:&nbsp;<code>application/json</code></li>
</ul>
</li>



<li>Send Body: ON → Body Content Type: JSON → Specify Body: Using JSON</li>



<li>JSON Body:</li>
</ul>



<pre class="wp-block-code"><code>{
  "prompt": "={{ $json&#91;'`prompt`'] }}",
  "prompt_upsampling": true,
  "width": 1024,
  "height": 1024,
  "steps": 35,
  "guidance": 5,
  "output_format": "jpeg",
  "safety_tolerance": 2
}</code></pre>



<ul class="wp-block-list">
<li>Response Format: JSON<br>Die 35 Render-Steps liefern eine gute Balance zwischen Bildqualität und Generierungszeit (ca. 8–15 Sekunden).</li>
</ul>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440085d5fb&quot;}" data-wp-interactive="core/image" data-wp-key="69e440085d5fb" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="728" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-22-n8n-HTTP-Request-URL-Bild-1024x728.png" alt="BILD 22 - n8n - HTTP Request - URL Bild" class="wp-image-846" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-22-n8n-HTTP-Request-URL-Bild-1024x728.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-22-n8n-HTTP-Request-URL-Bild-300x213.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-22-n8n-HTTP-Request-URL-Bild-768x546.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-22-n8n-HTTP-Request-URL-Bild-1536x1092.png 1536w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-22-n8n-HTTP-Request-URL-Bild.png 1545w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 22 &#8211; n8n &#8211; HTTP Request &#8211; URL Bild</figcaption></figure>



<h4 class="wp-block-heading">3.6.10 Warten und Bild abrufen</h4>



<p>Da die API asynchron arbeitet, brauchen wir eine Poll-Schleife: warten -&gt; nachfragen -&gt; fertig oder nochmal warten.<br><strong>Wait-Node:</strong></p>



<ul class="wp-block-list">
<li>Node:&nbsp;<strong>Wait</strong></li>



<li>Resume: After Time Interval</li>



<li>Wait Amount:&nbsp;<strong>11</strong>&nbsp;Sekunden<br>11 Sekunden ist in der Praxis eine gute Wartezeit für Flux-2-Flex. Zu kurz führt zu vielen unnötigen Check-Requests, zu lang verlängert die Workflow-Laufzeit unnötig.<br><strong>Check-Node:</strong></li>



<li>Node:&nbsp;<strong>HTTP Request</strong>&nbsp;(Name:&nbsp;<code>HTTP Request - Check URL Bild</code>)</li>



<li>Method: GET</li>



<li>URL:&nbsp;<code>={{ $('HTTP Request - URL Bild').item.json.polling_url }}</code></li>



<li>Response Format: JSON<br><strong>IF-Node (fertig oder weiter warten):</strong></li>



<li>Node:&nbsp;<strong>IF</strong></li>



<li>Condition:&nbsp;<code>{{ $json.status }}</code>&nbsp;is equal to&nbsp;<code>Ready</code>
<ul class="wp-block-list">
<li><strong>TRUE</strong>&nbsp;→ weiter zum Download</li>



<li><strong>FALSE</strong>&nbsp;→ zurück zum Wait-Node (Verbindung vom FALSE-Ausgang zurück zu „Wait&#8220;)<br><strong>Achtung</strong>: BFL gibt&nbsp;<code>Ready</code>&nbsp;mit großem R zurück – nicht&nbsp;<code>READY</code>. Tippfehler hier führen zu einer Endlosschleife.<br><strong>Download-Node:</strong></li>
</ul>
</li>



<li>Node:&nbsp;<strong>HTTP Request</strong>&nbsp;(Name:&nbsp;<code>HTTP Request - Download URL Bild</code>)</li>



<li>Method: GET</li>



<li>URL:&nbsp;<code>={{ $json.result.sample }}</code></li>



<li>Response Format:&nbsp;<strong>File</strong><br>Das Bild landet jetzt als Binary-Daten im Feld&nbsp;<code>data</code>&nbsp;und ist bereit zum Speichern.</li>
</ul>



<h4 class="wp-block-heading">3.6.11 Dateinamen vergeben</h4>



<p>Ein&nbsp;<strong>Edit Fields-Node</strong>&nbsp;erstellt einen systematischen Dateinamen im Format&nbsp;<code>YYYY-MM-DD_quelle_artikel-slug_img-01.jpg</code>:</p>



<ul class="wp-block-list">
<li>Node:&nbsp;<strong>Edit Fields</strong>&nbsp;(Name:&nbsp;<code>Edit Fields5</code>)</li>



<li>Include Other Input Fields:&nbsp;<strong>ON</strong></li>



<li>Add Field → Name:&nbsp;<code>filename</code>&nbsp;→ Type: String → Value:</li>
</ul>



<pre class="wp-block-code"><code>={{ 
  (String($('Execute a SQL query').item.json.original_published_at || '').substring(0,10) || '0000-00-00')
}}_{{ 
  String($('Execute a SQL query').item.json.original_source || 'unknown').toLowerCase().replace(/\s+/g, '-').replace(/&#91;^a-z0-9-]/g,'')
}}_{{ 
  String($('Execute a SQL query').item.json.original_title || 'untitled')
    .toLowerCase()
    .normalize('NFD').replace(/&#91;\u0300-\u036f]/g, '')
    .replace(/&#91;^a-z0-9]+/g, '-')
    .replace(/^-+|-+$/g, '')
    .substring(0, 80)
}}_img-01.jpg</code></pre>



<p>Das Ergebnis:&nbsp;<code>2026-01-20_heise-it_openai-stellt-neues-modell-vor_img-01.jpg</code>. Jeder Dateiname ist eindeutig, lesbar und sortierbar nach Datum.</p>



<h4 class="wp-block-heading">3.6.12 Bild auf der Synology NAS speichern</h4>



<ul class="wp-block-list">
<li>Node:&nbsp;<strong>Read/Write Files from Disk</strong></li>



<li>Operation: Write File to Disk</li>



<li>Binary Property:&nbsp;<code>data</code></li>



<li>File Path:&nbsp;<code>/data/wpmedia/raw/{{ $json.filename }}</code><br>Damit n8n auf dieses Verzeichnis schreiben darf, muss das Volume im Docker-YAML gemountet sein. Falls noch nicht geschehen, ergänze in deiner&nbsp;<code>docker-compose.yml</code>&nbsp;unter&nbsp;<code>volumes</code>:</li>
</ul>



<pre class="wp-block-code"><code>volumes:
  - /volume2/docker/n8n/app_data:/home/node/.n8n
  - /volume1/WordPress/media:/data/wpmedia    # ← diese Zeile hinzufügen</code></pre>



<p>Danach den Container neu starten. Außerdem müssen die Schreibrechte für den n8n-Prozess stimmen &#8211; falls der Node einen Fehler meldet, hilft dieser SSH-Befehl auf der DiskStation</p>



<pre class="wp-block-code"><code>sudo chown -R 1000:1000 /volume1/WordPress/media/
sudo chmod -R 775 /volume1/WordPress/media/</code></pre>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440085e05b&quot;}" data-wp-interactive="core/image" data-wp-key="69e440085e05b" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="731" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-23-n8n-Read-Write-Files-form-Disk-1024x731.png" alt="BILD 23 - n8n - Read Write Files form Disk" class="wp-image-847" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-23-n8n-Read-Write-Files-form-Disk-1024x731.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-23-n8n-Read-Write-Files-form-Disk-300x214.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-23-n8n-Read-Write-Files-form-Disk-768x548.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-23-n8n-Read-Write-Files-form-Disk-1536x1096.png 1536w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-23-n8n-Read-Write-Files-form-Disk.png 1539w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 23 &#8211; n8n &#8211; Read Write Files form Disk</figcaption></figure>



<h4 class="wp-block-heading">3.6.13 Story in Datenbank aktualisieren</h4>



<p>Zum Abschluss schreibt ein&nbsp;<strong>Postgres-Node</strong>&nbsp;alle erzeugten Inhalte in die&nbsp;<code>ki_story</code>-Tabelle zurück und setzt den Status auf&nbsp;<code>PUBLISH_READY</code>. Das ist das Signal für Agent 5, dass dieser Artikel zur Veröffentlichung bereit steht.</p>



<ul class="wp-block-list">
<li>Node:&nbsp;<strong>Update rows in a table</strong></li>



<li>Credential to connect with:&nbsp;<code>n8n-postgres</code></li>



<li>Operation: Update</li>



<li>Schema: public</li>



<li>Table:&nbsp;<strong>ki_story</strong>&nbsp;(nicht ki_artikel!)</li>



<li>Mapping Column Mode: Map Each Column Manually</li>



<li>Columns to match on:&nbsp;<strong>id</strong></li>
</ul>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Feld</th><th>Value</th></tr></thead><tbody><tr><td>id (using to match)</td><td><code>={{ $('Execute a SQL query').item.json.story_id }}</code></td></tr><tr><td>status</td><td><code>PUBLISH_READY</code></td></tr><tr><td>wp_title</td><td><code>={{ $('Edit Fields2').item.json.wp_title }}</code></td></tr><tr><td>wp_content</td><td><code>={{ $('Edit Fields2').item.json.wp_content }}</code></td></tr><tr><td>wp_excerpt</td><td><code>={{ $('Edit Fields2').item.json.wp_excerpt }}</code></td></tr><tr><td>wp_tags</td><td><code>={{ $('Edit Fields2').item.json.wp_tags }}</code></td></tr><tr><td>image_file_path</td><td><code>={{ $json.fileName }}</code></td></tr></tbody></table></figure>



<p><code>$json.fileName</code>&nbsp;(mit großem N) ist der automatisch von n8n vergebene Name der gespeicherten Datei – er entspricht dem Wert aus&nbsp;<code>Edit Fields5</code>, wird aber direkt aus dem Read/Write-Node übernommen.</p>



<h4 class="wp-block-heading">3.6.14 Workflow veröffentlichen</h4>



<p>Stelle den Schedule Trigger auf&nbsp;<strong>23 Stunden</strong>&nbsp;und aktiviere den Workflow über&nbsp;<strong>Publish</strong>. Agent 4 läuft täglich einmal, nimmt die beste angereicherte Story, produziert daraus einen fertigen Artikel mit eigenem Coverbild und legt beides in der Datenbank ab.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440085e7f1&quot;}" data-wp-interactive="core/image" data-wp-key="69e440085e7f1" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="503" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-24-n8n-Fertiger-Workflow-4-Agent-Artikel-erstellen-mit-eigenem-Bild-1024x503.png" alt="BILD 24 - n8n - Fertiger Workflow - 4 Agent - Artikel erstellen mit eigenem Bild" class="wp-image-848" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-24-n8n-Fertiger-Workflow-4-Agent-Artikel-erstellen-mit-eigenem-Bild-1024x503.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-24-n8n-Fertiger-Workflow-4-Agent-Artikel-erstellen-mit-eigenem-Bild-300x147.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-24-n8n-Fertiger-Workflow-4-Agent-Artikel-erstellen-mit-eigenem-Bild-768x377.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-24-n8n-Fertiger-Workflow-4-Agent-Artikel-erstellen-mit-eigenem-Bild-1536x754.png 1536w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-24-n8n-Fertiger-Workflow-4-Agent-Artikel-erstellen-mit-eigenem-Bild.png 1772w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 24 &#8211; n8n &#8211; Fertiger Workflow &#8211; 4 Agent &#8211; Artikel erstellen mit eigenem Bild</figcaption></figure>



<h3 class="wp-block-heading">3.7 Agent 5: Veröffentlichen auf WordPress</h3>



<p><strong>Tanja</strong>: „Das ist der letzte Schritt, Agent 5 übergibt alles an WordPress.&#8220;<br><strong>Ulf:</strong> „Und dann ist der Artikel live?&#8220;<br><strong>Tanja</strong>: „Nein. Er landet als Entwurf. Du schaust drüber, gibst grünes Licht, und erst dann geht er online.&#8220;<br><strong>Bernd</strong>: „Warum nicht direkt veröffentlichen?&#8220; Dann spart man sich den Schritt.&#8220;<br><strong>Tanja</strong>: „Weil, KI-Artikel manchmal Fehler enthalten. Halluzinationen. Falsche Namen. Veraltete Zahlen. Ein kurzer menschlicher Blick verhindert, dass dein Blog Unsinn veröffentlicht, während du schläfst.&#8220;<br><strong>Bernd</strong> überlegt. „Ich hätte das direkt veröffentlicht.&#8220;<br><strong>Tanja</strong>: „Das weiß ich.&#8220;</p>



<h4 class="wp-block-heading">3.7.1 Vorbereitung in WordPress</h4>



<p>Damit n8n Artikel und Bilder hochladen darf, braucht es ein&nbsp;<strong>Anwendungspasswort</strong>. Das ist sicherer als dein normales Login – es kann jederzeit widerrufen werden, ohne dass sich dein Hauptpasswort ändert.</p>



<ol class="wp-block-list">
<li>Logge dich in dein&nbsp;<strong>WordPress-Admin</strong>&nbsp;ein</li>



<li>Lege unter&nbsp;<strong>Benutzer → Neu hinzufügen</strong>&nbsp;einen neuen Benutzer an, z. B.&nbsp;<code>n8n-publisher</code></li>



<li>Weise ihm die Rolle&nbsp;<strong>Autor</strong>&nbsp;oder&nbsp;<strong>Redakteur</strong>&nbsp;zu – er braucht keine Admin-Rechte</li>



<li>Öffne das Profil des neuen Benutzers und scrolle ganz nach unten zu&nbsp;<strong>Anwendungspasswörter</strong></li>



<li>Gib einen Namen ein (z. B.&nbsp;<code>n8n-Diskstation</code>) und klicke auf&nbsp;<strong>Neues Anwendungspasswort hinzufügen</strong></li>



<li><strong>Wichtig:</strong>&nbsp;Kopiere das angezeigte Passwort sofort (z. B.&nbsp;<code>abcd efgh ijkl ...</code>), es wird nur dieses eine Mal angezeigt</li>



<li>Notiere außerdem die&nbsp;<strong>Kategorie-ID</strong>&nbsp;deiner Ziel-Kategorie. Diese findest du in WordPress unter&nbsp;<strong>Beiträge -&gt; Kategorien</strong>: Klicke die gewünschte Kategorie an und lies die ID aus der URL ab (z. B.&nbsp;<code>...tag_ID=8</code>)</li>
</ol>



<h4 class="wp-block-heading">3.7.2 Den Workflow starten</h4>



<ol class="wp-block-list">
<li>Gehe zurück zur Workflow-Übersicht und klicke auf&nbsp;<strong>Create new workflow</strong></li>



<li>Nenne ihn oben links:&nbsp;<code>A5 Agent: Veröffentlichen auf WordPress</code></li>



<li>Klicke auf&nbsp;<strong>Add First Step</strong>&nbsp;und wähle&nbsp;<strong>Schedule Trigger</strong>
<ul class="wp-block-list">
<li>Trigger Interval: Hours</li>



<li>Hours Between Triggers:&nbsp;<strong>23</strong></li>



<li>Trigger at Minute: 0<br>Für den Aufbau nutzen wir zunächst den&nbsp;<strong>Manual Trigger</strong>, damit wir direkt testen können.</li>
</ul>
</li>
</ol>



<h4 class="wp-block-heading">3.7.3 Fertigen Artikel aus der Datenbank holen</h4>



<ul class="wp-block-list">
<li>Node:&nbsp;<strong>Postgres – Execute a SQL query</strong></li>



<li>Credential to connect with:&nbsp;<code>n8n-postgres</code></li>



<li>Query:</li>
</ul>



<pre class="wp-block-code"><code>SELECT
  id,
  wp_title,
  wp_content,
  wp_excerpt,
  wp_tags,
  image_file_path
FROM ki_story
WHERE status = 'PUBLISH_READY'
ORDER BY created_at DESC
LIMIT 1;</code></pre>



<p>Der Status&nbsp;<code>PUBLISH_READY</code>&nbsp;wird von Agent 4 automatisch gesetzt. Du kannst ihn in Metabase auch manuell vergeben oder entfernen – das gibt dir volle Kontrolle darüber, welche Artikel in die Veröffentlichungswarteschlange kommen.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440085f1fb&quot;}" data-wp-interactive="core/image" data-wp-key="69e440085f1fb" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="729" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-25-n8n-Execute-a-SQL-query-Artikel-aus-Datenbank-holen-1024x729.png" alt="BILD 25 - n8n - Execute a SQL query - Artikel aus Datenbank holen" class="wp-image-849" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-25-n8n-Execute-a-SQL-query-Artikel-aus-Datenbank-holen-1024x729.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-25-n8n-Execute-a-SQL-query-Artikel-aus-Datenbank-holen-300x213.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-25-n8n-Execute-a-SQL-query-Artikel-aus-Datenbank-holen-768x546.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-25-n8n-Execute-a-SQL-query-Artikel-aus-Datenbank-holen-1536x1093.png 1536w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-25-n8n-Execute-a-SQL-query-Artikel-aus-Datenbank-holen.png 1539w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 25 &#8211; n8n &#8211; Execute a SQL query &#8211; Artikel aus Datenbank holen</figcaption></figure>



<h4 class="wp-block-heading">3.7.4 Bild von der NAS laden</h4>



<p>Das Bild muss als Binary-Datei in den n8n-Arbeitsspeicher geladen werden, bevor es an WordPress übertragen werden kann.</p>



<ul class="wp-block-list">
<li>Node:&nbsp;<strong>Read/Write Files from Disk</strong></li>



<li>Operation: Read File(s) From Disk</li>



<li>File(s) Selector:&nbsp;<code>={{ $json.image_file_path }}</code><br>Der&nbsp;<code>image_file_path</code>&nbsp;aus der Datenbank enthält den vollständigen Pfad innerhalb des Docker-Containers, z. B.&nbsp;<code>/data/wpmedia/raw/2026-01-20_heise-it_openai-stellt-neues-modell-vor_img-01.jpg</code>. Dieser Pfad muss mit dem in Agent 4 gemounteten Volume übereinstimmen.</li>
</ul>



<h4 class="wp-block-heading">3.7.5 Bild in die WordPress-Mediathek hochladen</h4>



<p>WordPress braucht das Bild zuerst in der Mediathek, um ihm eine interne ID zuzuweisen – diese ID wird dann beim Erstellen des Beitrags als&nbsp;<code>featured_media</code>&nbsp;referenziert.</p>



<ul class="wp-block-list">
<li>Node:&nbsp;<strong>HTTP Request</strong>&nbsp;(Name:&nbsp;<code>HTTP Request</code>)</li>



<li>Method: POST</li>



<li>URL:&nbsp;<code>https://foundic.org/wp-json/wp/v2/media</code></li>



<li>Authentication: Generic Credential Type → Basic Auth</li>



<li>Basic Auth Credential →&nbsp;<strong>New Credential:</strong>
<ul class="wp-block-list">
<li>Username: dein n8n-Publisher-Benutzername</li>



<li>Password: das&nbsp;<strong>Anwendungspasswort</strong>&nbsp;(nicht das normale Login-Passwort!)</li>
</ul>
</li>



<li>Send Headers:&nbsp;<strong>ON</strong></li>
</ul>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Header Name</th><th>Value</th></tr></thead><tbody><tr><td>Content-Disposition</td><td><code>=attachment; filename="{{ $binary.data.fileName }}"</code></td></tr><tr><td>Content-Type</td><td><code>image/jpeg</code></td></tr></tbody></table></figure>



<ul class="wp-block-list">
<li>Send Body:&nbsp;<strong>ON</strong></li>



<li>Body Content Type:&nbsp;<strong>n8n Binary File</strong></li>



<li>Input Data Field Name:&nbsp;<code>data</code><br>Wenn der Request erfolgreich ist, gibt WordPress ein JSON-Objekt zurück, das u. a. das Feld&nbsp;<code>id</code>&nbsp;enthält – die Medien-ID des hochgeladenen Bildes. Diese ID brauchen wir im nächsten Schritt.</li>
</ul>



<h4 class="wp-block-heading">3.7.6 WordPress-Beitrag erstellen</h4>



<p>Jetzt wird der eigentliche Beitrag angelegt. Wichtig: Der Status ist bewusst auf&nbsp;<code>draft</code>&nbsp;gesetzt – der Artikel erscheint nicht sofort öffentlich, sondern landet zunächst als Entwurf in WordPress, wo er prüft und freigeben werden kann.</p>



<ul class="wp-block-list">
<li>Node:&nbsp;<strong>HTTP Request</strong>&nbsp;(Name:&nbsp;<code>HTTP Request1</code>)</li>



<li>Method: POST</li>



<li>URL:&nbsp;<code>https://foundic.org/wp-json/wp/v2/posts</code></li>



<li>Authentication: Generic Credential Type → Basic Auth → dasselbe Credential wie oben</li>



<li>Send Body:&nbsp;<strong>ON</strong></li>



<li>Body Content Type: JSON</li>



<li>Specify Body: Using Fields Below<br>Füge folgende Body-Felder hinzu (über&nbsp;<strong>Add Parameter</strong>):</li>
</ul>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Name</th><th>Value</th></tr></thead><tbody><tr><td>title</td><td><code>={{ $('Execute a SQL query').item.json.wp_title }}</code></td></tr><tr><td>content</td><td><code>={{ $('Execute a SQL query').item.json.wp_content }}</code></td></tr><tr><td>excerpt</td><td><code>={{ $('Execute a SQL query').item.json.wp_excerpt }}</code></td></tr><tr><td>featured_media</td><td><code>={{ $json.id }}</code>&nbsp;← Medien-ID aus dem vorherigen HTTP Request</td></tr><tr><td>status</td><td><code>draft</code></td></tr><tr><td>categories</td><td><code>8</code>&nbsp;← deine Kategorie-ID aus Schritt 3.7.1</td></tr></tbody></table></figure>



<p>Das Feld&nbsp;<code>featured_media</code>&nbsp;mit&nbsp;<code>{{ $json.id }}</code>&nbsp;referenziert die Bild-ID, die WordPress im vorherigen Schritt zurückgegeben hat – das verknüpft das hochgeladene Bild automatisch als Coverbild des Beitrags.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440085fcf5&quot;}" data-wp-interactive="core/image" data-wp-key="69e440085fcf5" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="729" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-26-n8n-HTTP-Request1-Wordpress-Beitrag-erstellen-1024x729.png" alt="BILD 26 - n8n - HTTP Request1 - WordPress Beitrag erstellen" class="wp-image-850" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-26-n8n-HTTP-Request1-Wordpress-Beitrag-erstellen-1024x729.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-26-n8n-HTTP-Request1-Wordpress-Beitrag-erstellen-300x214.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-26-n8n-HTTP-Request1-Wordpress-Beitrag-erstellen-768x547.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-26-n8n-HTTP-Request1-Wordpress-Beitrag-erstellen-1536x1094.png 1536w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-26-n8n-HTTP-Request1-Wordpress-Beitrag-erstellen.png 1543w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 26 &#8211; n8n &#8211; HTTP Request1 &#8211; WordPress Beitrag erstellen</figcaption></figure>



<h4 class="wp-block-heading">3.7.7 Status in der Datenbank aktualisieren</h4>



<p>Nach erfolgreicher Übergabe an WordPress wird der Status in&nbsp;<code>ki_story</code>&nbsp;auf&nbsp;<code>PUBLISHED</code>&nbsp;gesetzt, damit der Artikel beim nächsten Durchlauf nicht erneut verarbeitet wird.</p>



<ul class="wp-block-list">
<li>Node:&nbsp;<strong>Update rows in a table</strong></li>



<li>Credential to connect with:&nbsp;<code>n8n-postgres</code></li>



<li>Operation: Update</li>



<li>Schema: public</li>



<li>Table:&nbsp;<strong>ki_story</strong></li>



<li>Mapping Column Mode: Map Each Column Manually</li>



<li>Columns to match on:&nbsp;<strong>id</strong></li>
</ul>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Feld</th><th>Value</th></tr></thead><tbody><tr><td>id (using to match)</td><td><code>={{ $('Execute a SQL query').item.json.id }}</code></td></tr><tr><td>status</td><td><code>PUBLISHED</code></td></tr></tbody></table></figure>



<h4 class="wp-block-heading">3.7.8 Der Human-in-the-Loop: Freigabe in WordPress</h4>



<p>Nachdem Agent 5 gelaufen ist, liegt der Artikel als Entwurf in WordPress. Jetzt bist du dran – und das ist gut so:</p>



<ol class="wp-block-list">
<li>Logge dich in dein&nbsp;<strong>WordPress-Admin</strong>&nbsp;ein</li>



<li>Gehe zu&nbsp;<strong>Beiträge → Entwürfe</strong></li>
</ol>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e44008604d5&quot;}" data-wp-interactive="core/image" data-wp-key="69e44008604d5" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="737" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-27-WordPress-Entwurf-des-Beitrags-unter-Beitraege-1024x737.png" alt="BILD 27 - WordPress - Entwurf des Beitrags unter Beiträge" class="wp-image-852" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-27-WordPress-Entwurf-des-Beitrags-unter-Beitraege-1024x737.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-27-WordPress-Entwurf-des-Beitrags-unter-Beitraege-300x216.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-27-WordPress-Entwurf-des-Beitrags-unter-Beitraege-768x553.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-27-WordPress-Entwurf-des-Beitrags-unter-Beitraege.png 1342w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 27 &#8211; WordPress &#8211; Entwurf des Beitrags unter Beiträge</figcaption></figure>



<ol start="3" class="wp-block-list">
<li>Öffne den neu erstellten Beitrag und prüfe Titel, Text, Bild und Tags</li>



<li>Falls alles passt: Klicke auf&nbsp;<strong>Veröffentlichen</strong></li>



<li>Falls du Anpassungen möchtest: Bearbeite den Beitrag direkt in WordPress</li>
</ol>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400860b0f&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400860b0f" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="703" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-28-WordPress-Entwurf-des-Beitrags-kann-geprueft-geaendert-und-veroeffentlicht-werden-1024x703.png" alt="BILD 28 - WordPress - Entwurf des Beitrags kann geprüft, geändert und veröffentlicht werden" class="wp-image-853" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-28-WordPress-Entwurf-des-Beitrags-kann-geprueft-geaendert-und-veroeffentlicht-werden-1024x703.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-28-WordPress-Entwurf-des-Beitrags-kann-geprueft-geaendert-und-veroeffentlicht-werden-300x206.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-28-WordPress-Entwurf-des-Beitrags-kann-geprueft-geaendert-und-veroeffentlicht-werden-768x528.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-28-WordPress-Entwurf-des-Beitrags-kann-geprueft-geaendert-und-veroeffentlicht-werden.png 1530w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 28 &#8211; WordPress &#8211; Entwurf des Beitrags kann geprüft, geändert und veröffentlicht werden</figcaption></figure>



<p>Du kannst in Metabase jederzeit den aktuellen Status aller Artikel einsehen und den&nbsp;<code>status</code>-Wert manuell anpassen – z. B. um einen Artikel zurück auf&nbsp;<code>ANGEREICHERT</code>&nbsp;zu setzen, wenn Agent 4 ihn neu bearbeiten soll.</p>



<h4 class="wp-block-heading">3.7.9 Workflow veröffentlichen</h4>



<p>Stelle den Schedule Trigger auf&nbsp;<strong>23 Stunden</strong>&nbsp;und aktiviere über&nbsp;<strong>Publish</strong>. Die gesamte Pipeline läuft jetzt automatisch:</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400861177&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400861177" class="wp-block-image aligncenter size-large wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="683" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-29-n8n-Fertiger-Workflow-5-Agent-Veroeffentlichen-auf-WordPress-1024x683.png" alt="BILD 29 - n8n - Fertiger Workflow - 5 Agent - Veröffentlichen auf WordPress" class="wp-image-855" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-29-n8n-Fertiger-Workflow-5-Agent-Veroeffentlichen-auf-WordPress-1024x683.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-29-n8n-Fertiger-Workflow-5-Agent-Veroeffentlichen-auf-WordPress-300x200.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-29-n8n-Fertiger-Workflow-5-Agent-Veroeffentlichen-auf-WordPress-768x512.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-29-n8n-Fertiger-Workflow-5-Agent-Veroeffentlichen-auf-WordPress.png 1536w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 29 &#8211; n8n &#8211; Fertiger Workflow &#8211; 5 Agent &#8211; Veröffentlichen auf WordPress</figcaption></figure>



<ul class="wp-block-list">
<li>Alle&nbsp;<strong>2 Stunden</strong>&nbsp;liest Agent 1 neue Artikel aus 22 RSS-Feeds ein</li>



<li>Alle&nbsp;<strong>4 Stunden</strong>&nbsp;bewertet Agent 2 die neuen Einträge</li>



<li>Alle&nbsp;<strong>23 Stunden</strong>&nbsp;reichert Agent 3 die besten Artikel mit Web-Kontext an</li>



<li>Alle&nbsp;<strong>23 Stunden</strong>&nbsp;schreibt Agent 4 den fertigen Artikel und generiert das Coverbild</li>



<li>Alle&nbsp;<strong>23 Stunden</strong>&nbsp;lädt Agent 5 den Artikel als Entwurf in WordPress hoch – und wartet auf deine Freigabe bzw. Veröffentlichung in WordPress.</li>
</ul>



<h2 class="wp-block-heading">4 Fazit</h2>



<p><strong>Einige Wochen später. Gleiches Büro. Gleicher Montag.</strong><br><strong>Ulf</strong> öffnet seinen Laptop, nicht um Feeds zu durchklicken, sondern um einen einzigen Entwurf in WordPress zu prüfen. Der Artikel ist fertig geschrieben, hat ein Coverbild, Quellen und Tags. Er liest ihn durch, nickt, klickt auf „Veröffentlichen&#8220;.<br>Drei Minuten. Statt einer Stunde.<br><strong>Bernd</strong> schaut herüber: „Hast du das alles selbst geschrieben?&#8220;<br><strong>Ulf</strong>: „Eine KI hat es geschrieben, ich hab es nur freigegeben.&#8220;<br><strong>Bernd</strong>: „Und das ist… okay so?&#8220;<br><strong>Tanja</strong> lehnt sich zurück: „Das ist genau der Punkt.&#8220;</p>



<h3 class="wp-block-heading">Was du gebaut hast</h3>



<p>Wenn du alle fünf Agenten eingerichtet und aktiviert hast, läuft auf deiner Synology NAS ein vollautomatischer digitaler Newsroom – rund um die Uhr, ohne dass du jeden Morgen Feeds durchklicken oder manuell recherchieren musst. MEehrere Nachrichtenquellen (RSS-Feeds) werden kontinuierlich beobachtet, jede Meldung bewertet, die relevantesten Treffer tiefenrecherchiert, ein kompletter WordPress-Artikel geschrieben und ein eigenes Coverbild generiert. Was früher Stunden an redaktioneller Routinearbeit gekostet hätte, läuft heute im Hintergrund – und landet als Entwurf in deinem WordPress, wartet auf deinen letzten Blick und einen Klick.</p>



<p>Das ist kein Spielzeugprojekt. Du hast dabei ein ernsthaftes Stück Software-Architektur gebaut: eine relationale Datenbank mit Statusmaschine, ein Pipeline-System mit fünf unabhängig laufenden Agenten, Qualitätsprüfungen auf mehreren Ebenen, URL-Normalisierung zur Duplikatsvermeidung und einen Wissensgraphen aus verlinkten Artikeln. Und das alles ohne eine einzige Zeile Server-Code schreiben zu müssen.</p>



<h3 class="wp-block-heading">Was das System wirklich leistet – und was nicht</h3>



<p>Es lohnt sich, ehrlich zu sein: Das System schreibt gute, strukturierte, rechtskonforme Artikel. Aber es schreibt keine großartigen Artikel. Claude produziert soliden Redaktionsjournalismus – korrekt, gut aufgebaut, mit Quellen. Was fehlt, ist die menschliche Perspektive: die unerwartete Analogie, die pointierte Meinung, der Erfahrungswert aus zehn Jahren im Thema. Das System ist ein sehr guter erster Entwurf – aber ein Entwurf.</p>



<p>Genau deshalb ist der Human-in-the-Loop-Schritt kein lästiges Hindernis, sondern das Herzstück des Konzepts. Der Newsroom übernimmt die Fleißarbeit. Du übernimmst das Urteilsvermögen.</p>



<h3 class="wp-block-heading">Was du jetzt tun kannst</h3>



<p>Das System ist so gebaut, dass es wächst. Ein paar naheliegende nächste Schritte:</p>



<ul class="wp-block-list">
<li><strong>Mehr Quellen</strong>&nbsp;– du kannst beliebig viele weitere RSS-Feeds in Agent 1 einbinden, ohne den Rest des Systems anzufassen. Englischsprachige Quellen wie TechCrunch, The Verge oder MIT Technology Review würden die internationale Perspektive deutlich verbessern.</li>



<li><strong>Feinere Bewertung</strong>&nbsp;– der Scoring-Prompt in Agent 2 lässt sich jederzeit anpassen. Wenn du merkst, dass bestimmte Subkategorien zu oft oder zu selten auftauchen, justiere einfach die Beschreibungen oder die Schwellenwerte.</li>



<li><strong>Mehrsprachigkeit</strong>&nbsp;– Claude schreibt problemlos auf Englisch, wenn du den Prompt in Agent 4 entsprechend anpasst. Damit ließe sich derselbe Workflow für einen zweiten Blog in einer anderen Sprache nutzen.</li>



<li><strong>Tags automatisch anreichern</strong>&nbsp;– die von Claude generierten&nbsp;<code>wp_tags</code>&nbsp;könnten zusätzlich gegen eine feste Tag-Taxonomie in WordPress abgeglichen werden, damit keine Tippvarianten entstehen.</li>



<li><strong>Benachrichtigungen</strong>&nbsp;– ein zusätzlicher n8n-Workflow könnte dich per E-Mail oder Telegram benachrichtigen, sobald ein neuer Artikel als Entwurf in WordPress bereitliegt.</li>
</ul>



<h3 class="wp-block-heading">Das größere Bild</h3>



<p>Dieses Projekt zeigt exemplarisch, wohin die Reise mit KI-Automatisierung geht: nicht darum, Menschen zu ersetzen, sondern darum, den eigenen Hebel zu verlängern. Eine einzelne Person kann mit diesem Setup eine Publikationsfrequenz aufrechterhalten, die früher ein kleines Redaktionsteam erfordert hätte – und das zu Betriebskosten von unter 5 Euro im Monat.</p>



<p>n8n ist dabei das eigentliche Geheimnis. Nicht weil es besser wäre als Zapier oder Make in jeder einzelnen Funktion, sondern weil es&nbsp;<strong>self-hosted</strong>&nbsp;läuft. Deine Workflows, deine Daten, deine Infrastruktur – auf deiner eigenen Hardware, ohne monatliche Plattformgebühren, ohne Vendor-Lock-in, ohne Datenschutzbedenken beim Verarbeiten von Artikelinhalten.</p>



<p>Wenn du dieses System aufgebaut hast, hast du nicht nur einen Newsroom gebaut. Du hast verstanden, wie Multi-Agenten-Systeme funktionieren, wie man KI-Outputs in echte Workflows einbettet und wie man Automatisierung so gestaltet, dass sie skalierbar, wartbar und kontrollierbar bleibt. Das sind Fähigkeiten, die weit über dieses eine Projekt hinaus nützlich sein werden.</p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.foundic.org/de/ki-newsroom-n8n-synology-nas-automatisierung/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Sicherer Zugriff mit Cloudflare Tunnel auf n8n (Synology NAS Diskstation DS1621+)</title>
		<link>https://www.foundic.org/de/n8n-cloudflare-tunnel-synology-nas/</link>
					<comments>https://www.foundic.org/de/n8n-cloudflare-tunnel-synology-nas/#respond</comments>
		
		<dc:creator><![CDATA[Michael Müller]]></dc:creator>
		<pubDate>Sun, 15 Feb 2026 11:29:55 +0000</pubDate>
				<category><![CDATA[Projekte]]></category>
		<guid isPermaLink="false">https://www.foundic.org/?p=636</guid>

					<description><![CDATA[Es gibt diesen Moment, den viele kennen:&#160;n8n läuft sauber im eigenen Netzwerk (eine exakte Step-by-Step Anleitung zur Einrichtung von n8n via Docker findet ihr übrigens&#160;hier). Die ersten Workflows klicken, Webhooks funktionieren lokal – und dann kommt der Wunsch nach außen. Zugriff von unterwegs. Verlässliche URLs für Stripe, GitHub oder Telegram. Aber bitte&#160;ohne Portfreigaben, ohne Bastellösungen [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Es gibt diesen Moment, den viele kennen:&nbsp;<strong>n8n läuft sauber im eigenen Netzwerk</strong> (eine exakte Step-by-Step Anleitung zur Einrichtung von n8n via Docker findet ihr übrigens&nbsp;<a href="https://www.foundic.org/de/n8n-selbst-hosten-synology-nas-docker-installation/">hier</a>). Die ersten Workflows klicken, Webhooks funktionieren lokal – und dann kommt der Wunsch nach außen. Zugriff von unterwegs. Verlässliche URLs für Stripe, GitHub oder Telegram. Aber bitte&nbsp;<strong>ohne Portfreigaben</strong>, ohne Bastellösungen und ohne das ungute Gefühl, das eigene NAS nackt ins Internet zu stellen.<br>Genau hier kommt&nbsp;<strong>Cloudflare Tunnel</strong>&nbsp;ins Spiel. Kein Zauber, kein Marketingversprechen sondern eine nüchterne, erstaunlich elegante Lösung.</p>



<p><strong>Um diese Anleitung verständlicher zu machen, begleiten dich drei Personen:</strong><br>Die typischen Büro-Charaktere: Die kompetente IT-Kollegin, der selbsternannte Experte und der ehrliche Anfänger. Diese drei Perspektiven helfen dir, typische Stolperfallen zu erkennen und n8n wirklich zu verstehen.</p>



<p><strong>Tanja</strong> ist die IT-Expertin. Sie weiß, wie n8n funktioniert, erklärt geduldig und strukturiert – und lässt sich von schlechten Ratschlägen nicht aus der Ruhe bringen. Wenn du eine Frage hast, hat Tanja die Antwort.<br><strong>Bernd</strong> ist der selbsternannte „Experte“, der alles besser weiß und meistens falsch liegt. Seine Abkürzungen und sein Halbwissen führen regelmäßig zu Problemen. Er steht für alle gefährlichen Mythen und schlechten Praktiken, die du vermeiden solltest.<br><strong>Ulf</strong> ist der Lernende, genau wie du. Er stellt die Fragen, die dir im Kopf herumschwirren, und braucht manchmal einen Vergleich aus dem Alltag, um IT zu verstehen. Wenn Ulf etwas nicht versteht, ist das völlig in Ordnung dafür ist Tanja da.</p>



<p><strong>&#8222;Und… Action!&#8220;</strong></p>



<p><strong>Ulf</strong>&nbsp;lehnt sich zurück und verschränkt die Arme: „Moment mal. Ich hab n8n jetzt auf meinem NAS laufen, das Ding macht seine Workflows warum soll ich mir jetzt Stress mit irgendwelchen Tunneln machen? Kann ich nicht einfach einen Port aufmachen und gut is?&#8220;<br><strong>Bernd</strong>&nbsp;nickt selbstgefällig: „Genau! Port 5678 nach außen freigeben, fertig. Hab ich früher mit meinem alten Webserver auch so gemacht. Hat… na ja, meistens funktioniert.&#8220;<br><strong>Tanja</strong>&nbsp;schaut skeptisch. „Bis deine IP-Adresse auf einer Bot-Liste landete und du jede Minute Login-Versuche aus Kasachstan hattest, oder?&#8220;<br><strong>Bernd</strong> zuckt mit den Schultern: „War halt lebhaft.&#8220;<br><strong>Tanja</strong> seufzt: „Eine Portfreigabe ist wie eine offene Tür in deinem Haus mit einem Schild dran: ‚Bitte klopfen, bevor ihr einbrecht.&#8216; Cloudflare Tunnel macht etwas Eleganteres: Der Tunnel baut eine Verbindung&nbsp;<strong>von innen nach außen</strong>&nbsp;auf. Niemand kann bei dir anklopfen, weil die Tür von außen gar nicht existiert.&#8220;<br><strong>Ulf</strong> runzelt die Stirn: „Das klingt wie Fußballtaktik. Wir verteidigen nicht, wir haben einfach keinen Strafraum?&#8220;<br><strong>Tanja</strong>: &#8222;Ziemlich genau. Und Cloudflare steht als Torwart vor dem Tunnel – und lässt nur durch, was durchkommen soll.&#8220;</p>



<h3 class="wp-block-heading">1 Warum Cloudflare?</h3>



<p>Cloudflare ist eigentlich dafür bekannt, dass es vor Websites sitzt und böswilligen Traffic abfängt, bevor er überhaupt ankommt. Ein&nbsp;<strong>Reverse Proxy</strong>&nbsp;gewissermaßen eine Art Türsteher, der entscheidet, wer rein darf und wer draußen bleiben muss.<br>Der Cloudflare Tunnel macht etwas Ähnliches, nur umgekehrt: Statt dass dein Server auf eingehende Verbindungen wartet (und dafür einen Port öffnen muss), baut der Tunnel eine verschlüsselte Verbindung&nbsp;<em>von innen nach außen</em>&nbsp;auf. Cloudflare sitzt dann vor dieser Verbindung und leitet nur durch, was durchkommen soll.</p>



<p>Das hat vier entscheidende Vorteile:</p>



<ul class="wp-block-list">
<li><strong>Keine offenen Ports</strong>: Deine Firewall bleibt zu. Niemand kann deine NAS direkt scannen oder angreifen.</li>



<li><strong>Automatisches HTTPS</strong>: Cloudflare kümmert sich um SSL-Zertifikate. Du musst nichts erneuern, nichts konfigurieren.</li>



<li><strong>Schutz vor Bots &amp; DDoS</strong>: Cloudflare filtert Millionen von Anfragen pro Sekunde. Deine NAS bekommt nur legitimen Traffic zu sehen.</li>



<li><strong>Login-Schutz per E-Mail / MFA</strong>: Du kannst vor n8n eine zusätzliche Authentifizierungsschicht setzen – ohne dass n8n selbst davon weiß.</li>



<li><strong>Stabile Webhook-URLs</strong>: Externe Dienste wie Stripe oder Telegram brauchen URLs, die sich nicht ändern und immer erreichbar sind. Cloudflare liefert das.</li>
</ul>



<p><strong>Ulf</strong>: „Klingt zu gut, um wahr zu sein. Was ist der Haken?&#8220;<br><strong>Tanja</strong>: „Der Haken ist, dass du eine&nbsp;<strong>eigene Domain</strong>&nbsp;brauchst. Die muss nicht teuer sein oft reichen 10 Euro im Jahr, aber ohne Domain geht&#8217;s nicht. Cloudflare muss wissen, welche Adresse es für dich verwalten soll.&#8220;<br><strong>Bernd</strong> grinst: „Ich hab mal eine Domain gekauft.&nbsp;<code>bernd-ist-der-beste.de</code>. Leider hat sie niemand besucht.&#8220;<br><strong>Tanja</strong> murmelt: „Überraschung&#8220;.</p>



<h3 class="wp-block-heading">2 Überblick: Die Einrichtung in vier Schritten</h3>



<ol class="wp-block-list">
<li>Cloudflare-Konto &amp; Domain einrichten</li>



<li>Cloudflare Tunnel als Docker-Container auf Diskstation einrichten</li>



<li>n8n-Container auf die neue URL vorbereiten</li>



<li>Zugriff über Cloudflare Zero Trust absichern</li>
</ol>



<p>Wir gehen bewusst&nbsp;<strong>Schritt für Schritt</strong>&nbsp;klickbar, nachvollziehbar, ohne Vorwissen vorauszusetzen.</p>



<h4 class="wp-block-heading">2.1 Schritt: Cloudflare-Konto &amp; Domain einrichten</h4>



<h5 class="wp-block-heading">Registrierung &amp; Domain hinzufügen</h5>



<p>Geh auf&nbsp;<a href="https://cloudflare.com/" target="_blank" rel="noopener">Cloudflare.com</a>&nbsp;und erstelle einen Account, falls du noch keinen hast. Nach dem Login bzw. Registrierung klickst du auf <strong>Domains -&gt; Onboard a domain -&gt; Enter an existing domain</strong> und gibst deine Domain ein also etwa&nbsp;<code>deine-domain.de</code>.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440086a6db&quot;}" data-wp-interactive="core/image" data-wp-key="69e440086a6db" class="wp-block-image aligncenter size-large is-resized wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="739" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-1-Cloudflare-Dashboard-mit-dem-Button-22Add-Site22-und-Eingabefeld-fuer-die-Domain-1024x739.png" alt="BILD 1 - Cloudflare Dashboard mit dem Button &quot;Add Site&quot; und Eingabefeld für die Domain" class="wp-image-639" style="aspect-ratio:1.385671292788014;width:822px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-1-Cloudflare-Dashboard-mit-dem-Button-22Add-Site22-und-Eingabefeld-fuer-die-Domain-1024x739.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-1-Cloudflare-Dashboard-mit-dem-Button-22Add-Site22-und-Eingabefeld-fuer-die-Domain-300x216.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-1-Cloudflare-Dashboard-mit-dem-Button-22Add-Site22-und-Eingabefeld-fuer-die-Domain-768x554.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-1-Cloudflare-Dashboard-mit-dem-Button-22Add-Site22-und-Eingabefeld-fuer-die-Domain-1536x1108.png 1536w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-1-Cloudflare-Dashboard-mit-dem-Button-22Add-Site22-und-Eingabefeld-fuer-die-Domain.png 1630w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 1 &#8211; Cloudflare Dashboard mit dem Button &#8222;Add Site&#8220; und Eingabefeld für die Domain</figcaption></figure>



<p>Cloudflare bietet dir dann verschiedene Pläne an. Wähle den&nbsp;<strong>Free Plan</strong>&nbsp; aus, der reicht vollkommen aus.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440086ad10&quot;}" data-wp-interactive="core/image" data-wp-key="69e440086ad10" class="wp-block-image aligncenter size-full is-resized wp-lightbox-container"><img loading="lazy" decoding="async" width="1631" height="1178" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-2-Auswahl-eines-Cloudfare-Plans.png" alt="BILD 2 - Auswahl eines Cloudfare Plans" class="wp-image-640" style="aspect-ratio:1.3845621322256836;width:818px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-2-Auswahl-eines-Cloudfare-Plans.png 1631w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-2-Auswahl-eines-Cloudfare-Plans-300x217.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-2-Auswahl-eines-Cloudfare-Plans-1024x740.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-2-Auswahl-eines-Cloudfare-Plans-768x555.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-2-Auswahl-eines-Cloudfare-Plans-1536x1109.png 1536w" sizes="auto, (max-width: 1631px) 100vw, 1631px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 2 &#8211; Auswahl eines Cloudfare Plans</figcaption></figure>



<p><strong>Tanja</strong> nickt. „Gute Frage. Im Moment noch gar nichts. Du sagst Cloudflare nur: ‚Hey, ich hab diese Domain, kannst du sie für mich verwalten?&#8216; Aber die Kontrolle bekommst du erst, wenn du die&nbsp;<strong>Nameserver</strong>&nbsp;änderst. Das kommt jetzt.&#8220;</p>



<h5 class="wp-block-heading">Nameserver ändern</h5>



<p>Jetzt kommt der entscheidende Schritt: Cloudflare muss die Kontrolle über deine Domain übernehmen. Dafür musst du die&nbsp;<strong>Nameserver</strong>&nbsp;ändern.<br><strong>Was sind Nameserver?</strong>&nbsp;Stell dir vor, das Internet ist eine riesige Stadt, und deine Domain ist eine Adresse. Nameserver sind das Telefonbuch sie entscheiden, welche IP-Adresse hinter einer Domain steckt. Wenn jemand&nbsp;<code>deine-domain.de</code>aufruft, fragt sein Browser die Nameserver: „Wo finde ich die?&#8220;<br>Cloudflare zeigt dir auf der Seite&nbsp;<strong>&#8222;Change your nameservers&#8220;</strong>&nbsp;oder unter <strong>Configure DNS -&gt; DNS -&gt; Records -&gt; Cloudfare Nameservers</strong> zwei Adressen an, etwa (der Name vor dem ersten Punkt kann anders sein):</p>



<ul class="wp-block-list">
<li><code>aurora.ns.cloudflare.com</code></li>



<li><code>ben.ns.cloudflare.com</code></li>
</ul>



<p>Diese beiden Nameserver musst du bei deinem Domain-Hoster eintragen. Wo genau das ist, hängt vom Anbieter ab. Schau unter&nbsp;<strong>Domainverwaltung -&gt; DNS -&gt; NS-Record</strong>&nbsp;oder unter&nbsp;<strong>Manage Domain -&gt; Tools -&gt; Nameserver</strong>. Trage dort die beiden Cloudflare-Nameserver ein und lösche die alten.</p>



<p><strong>Ulf</strong>: „Warte mal. Ich lösche die alten? Was passiert denn dann mit meiner Website?&#8220;<br><strong>Tanja</strong>: „Kurzzeitig kann es sein, dass deine Domain nicht erreichbar ist. Das nennt sich DNS-Propagierung, die neuen Nameserver müssen sich erstmal im Internet verbreiten. Dauert meistens ein paar Minuten, kann aber bis zu 24 Stunden dauern.&#8220;<br><strong>Bernd</strong> grinst: „Bei mir hat&#8217;s drei Tage gedauert. Aber ich hab auch vergessen, auf ‚Speichern&#8216; zu klicken.&#8220;</p>



<p>Die Änderung kann bis zu&nbsp;<strong>24 Stunden</strong>&nbsp;dauern meistens geht&#8217;s schneller. Auf der Cloudflare-Plattform siehst du unter&nbsp;<strong>Overview -&gt; Check Nameservers</strong>, ob die Umstellung abgeschlossen ist.</p>



<h5 class="wp-block-heading">E-Mail-Verifizierung</h5>



<p>Irgendwann in diesem Prozess, oft während du auf die Nameserver-Prüfung wartest, wirst du von Cloudfare aufgefordert, deine E-Mail-Adresse zu bestätigen. Klick einfach den Link in der Mail, die du bekommst. Ohne diese Verifizierung geht es nicht weiter. Danach kannst Du ersten Tunnel anlegen.</p>



<p><strong>Ulf</strong> genervt: „Warum schicken die mir jetzt eine Mail?&#8220;<br><strong>Tanja</strong>: „Weil sie sicherstellen wollen, dass du nicht irgendeine Domain registrierst, die dir nicht gehört. Wenn jemand&nbsp;<code>google.de</code>&nbsp;bei Cloudflare anmelden könnte, ohne Besitzer zu sein, hätten wir ein Problem.&#8220;<br><strong>Bernd</strong> nickt: „Hab ich auch mal versucht. Hat nicht geklappt.&#8220;</p>



<h5 class="wp-block-heading">Ersten Tunnel anlegen</h5>



<p>Sobald die Domain eingerichtet ist, kannst du den ersten Tunnel anlegen. Geh auf&nbsp;<strong>Account Home -&gt; Zero Trust</strong> (nicht im Menü sondern rechts auf der Seite) <strong>-&gt; Networks -&gt; Add Tunnels -&gt; Create a tunnel</strong> (Alternativ: Zero Trust -&gt; Networks -&gt; Connectors -&gt; Tunnels).</p>



<p>Wähle&nbsp;<strong>Select Cloudflared</strong>&nbsp;als Tunnel-Typ, gib einen frei wählbaren Namen ein (z. B.&nbsp;<code>n8n-tunnel</code>).</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440086b632&quot;}" data-wp-interactive="core/image" data-wp-key="69e440086b632" class="wp-block-image aligncenter size-large is-resized wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="740" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-3-Create-a-tunnel-Select-Cloudfared-tunnel-type-1024x740.png" alt="BILD 3 - Create a tunnel - Select Cloudfared tunnel type" class="wp-image-641" style="width:832px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-3-Create-a-tunnel-Select-Cloudfared-tunnel-type-1024x740.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-3-Create-a-tunnel-Select-Cloudfared-tunnel-type-300x217.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-3-Create-a-tunnel-Select-Cloudfared-tunnel-type-768x555.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-3-Create-a-tunnel-Select-Cloudfared-tunnel-type-1536x1111.png 1536w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-3-Create-a-tunnel-Select-Cloudfared-tunnel-type.png 1632w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 3 &#8211; Create a tunnel &#8211; Select Cloudfared tunnel type</figcaption></figure>



<p>Auf der nächsten Seite zeigt Cloudflare dir ein langes&nbsp;<strong>Token</strong>. Den brauchst du gleich, kopiere diesen. Du bekommst es später nicht mehr zu sehen.</p>



<p><strong>Ulf</strong> skeptisch: „Wie lang ist das Ding?&#8220;<br><strong>Tanja</strong>: „Lang! Sieht aus wie eine Passwort-Explosion. Aber genau das macht ihn sicher. Kopier ihn in eine Textdatei, du brauchst ihn im nächsten Schritt.&#8220;</p>



<p>Klicke auf&nbsp;<strong>Next</strong>&nbsp;und fülle folgende Felder aus:</p>



<ul class="wp-block-list">
<li><strong>Subdomain</strong>:&nbsp;<code>n8n</code>&nbsp;(frei wählbar)</li>



<li><strong>Domain</strong>: Wähle deine Domain aus der Liste</li>



<li><strong>Type</strong>:&nbsp;<code>HTTP</code></li>



<li><strong>URL</strong>:&nbsp;<code>localhost:5678</code>(das ist der lokale Port von n8n auf deiner DiskStation)</li>
</ul>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440086bd05&quot;}" data-wp-interactive="core/image" data-wp-key="69e440086bd05" class="wp-block-image aligncenter size-large is-resized wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="738" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-4-Cloudflare-Tunnel-Konfiguration-mit-Subdomain-Domain-Type-und-URL-Feldern-1024x738.png" alt="BILD 4 - Cloudflare Tunnel-Konfiguration mit Subdomain-, Domain-, Type- und URL-Feldern" class="wp-image-642" style="width:842px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-4-Cloudflare-Tunnel-Konfiguration-mit-Subdomain-Domain-Type-und-URL-Feldern-1024x738.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-4-Cloudflare-Tunnel-Konfiguration-mit-Subdomain-Domain-Type-und-URL-Feldern-300x216.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-4-Cloudflare-Tunnel-Konfiguration-mit-Subdomain-Domain-Type-und-URL-Feldern-768x554.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-4-Cloudflare-Tunnel-Konfiguration-mit-Subdomain-Domain-Type-und-URL-Feldern-1536x1107.png 1536w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-4-Cloudflare-Tunnel-Konfiguration-mit-Subdomain-Domain-Type-und-URL-Feldern.png 1633w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 4 &#8211; Cloudflare Tunnel-Konfiguration mit Subdomain-, Domain-, Type- und URL-Feldern</figcaption></figure>



<p><strong>Ulf</strong>: „Was ist denn jetzt eine Subdomain?&#8220;<br><strong>Tanja</strong>: „Eine Subdomain ist wie ein Zimmer in deinem Haus. Deine Domain ist das Haus&nbsp;<code>deine-domain.de</code>. Die Subdomain ist ein bestimmter Raum darin&nbsp;<code>n8n.deine-domain.de</code>. Das gibt dir die Möglichkeit, für n8n eine eigene Adresse zu haben, ohne dass du gleich eine neue Domain kaufen musst.&#8220;<br><strong>Bernd</strong> nickt weise: „Ich hab mal&nbsp;<code>admin.bernd-ist-der-beste.de</code>&nbsp;angelegt. Dann hab ich das Passwort vergessen.&#8220;</p>



<p>Eine&nbsp;<strong>Subdomain</strong>&nbsp;ist sinnvoll, weil sie einen klar abgegrenzten technischen Zugriffspunkt&nbsp;schafft, über den du Sicherheit, Zugriffsregeln und Webhooks&nbsp;unabhängig von der Hauptdomain&nbsp;steuern kannst ohne andere Dienste oder Inhalte deiner Domain zu beeinflussen.<br>Klicke auf&nbsp;<strong>Save tunnel</strong>. Fertig. Der Tunnel ist angelegt, allerdings noch nicht aktiv, weil der&nbsp;<strong>Cloudflared</strong>-Container auf deiner Diskstation noch fehlt. Den richten wir jetzt ein.</p>



<h4 class="wp-block-heading">2.2 Schritt: Cloudflare Tunnel als Docker-Container auf Diskstation einrichten</h4>



<p><strong>Ulf</strong>: „Okay. Jetzt wird&#8217;s ernst. Wir basteln am NAS rum.&#8220;<br><strong>Tanja</strong>: „Richtig, aber keine Panik. Wir laden nur einen Container herunter und starten ihn. Das ist weniger kompliziert, als es klingt.&#8220;<br><strong>Bernd</strong> grinst: „Ich hab mal einen Container gestartet. Der hat dann alle anderen Container gekillt.&#8220;<br><strong>Tanja</strong>: „Weil du vergessen hast, das Netzwerk richtig zu setzen. Deshalb machen wir&#8217;s jetzt Schritt für Schritt.&#8220;</p>



<h5 class="wp-block-heading">Container herunterladen &amp; starten</h5>



<p>Öffne den&nbsp;<strong>Container Manager</strong>&nbsp;auf deiner Synology und gehe zu&nbsp;<strong>Registrierung</strong>.</p>



<ul class="wp-block-list">
<li><strong>Container Manager → Registrierung</strong></li>



<li>Image suchen:&nbsp;<code>cloudflare/cloudflared</code></li>



<li>Tag:&nbsp;<code>latest</code>&nbsp;herunterladen</li>
</ul>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440086c48d&quot;}" data-wp-interactive="core/image" data-wp-key="69e440086c48d" class="wp-block-image aligncenter size-large is-resized wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="829" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-5-Synology-Container-Manager-–-cloudflarecloudflared-Image-1024x829.png" alt="BILD 5 - Synology Container Manager – cloudflare/cloudflared Image" class="wp-image-643" style="aspect-ratio:1.2352350806762913;width:868px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-5-Synology-Container-Manager-–-cloudflarecloudflared-Image-1024x829.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-5-Synology-Container-Manager-–-cloudflarecloudflared-Image-300x243.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-5-Synology-Container-Manager-–-cloudflarecloudflared-Image-768x622.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-5-Synology-Container-Manager-–-cloudflarecloudflared-Image.png 1209w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 5 &#8211; Synology Container Manager – cloudflare/cloudflared Image</figcaption></figure>



<p><strong>Ulf</strong>: „Was ist denn ein Image?&#8220;<br><strong>Tanja</strong>: „Ein Image ist wie ein Bauplan. Der Container ist das fertige Haus, das nach diesem Bauplan gebaut wird. Du lädst den Bauplan herunter, und im nächsten Schritt baust du das Haus.&#8220;</p>



<h5 class="wp-block-heading">Container erstellen</h5>



<p>Sobald das Image heruntergeladen ist, klickst du es an und wählst&nbsp;<strong>Ausführen</strong>. Jetzt kommt der Assistent, der dich durch die Einrichtung führt.<br>Wichtig: Folgende Einstellungen sind entscheidend:</p>



<ul class="wp-block-list">
<li><strong>Automatischen Neustart aktivieren</strong>: Setzt du ein Häkchen. Damit startet der Container automatisch neu, falls dein NAS mal neu startet.</li>



<li><strong>Netzwerk</strong>: Wähle&nbsp;<strong>host</strong>&nbsp;(nicht bridge!). Das ist wichtig, damit der Container auf&nbsp;<code>localhost:5678</code>&nbsp;zugreifen kann – also auf deinen n8n-Container.</li>
</ul>



<p><strong>Ulf</strong>: „Warum host?&#8220;<br><strong>Tanja</strong>: „Weil der Cloudflare-Container mit deinem n8n-Container sprechen muss. Wenn du&nbsp;<code>bridge</code>&nbsp;wählst, sieht der Cloudflare-Container&nbsp;<code>localhost:5678</code>&nbsp;nicht weil&nbsp;<code>localhost</code>&nbsp;dann nur den Container selbst meint, nicht dein NAS. Mit&nbsp;<code>host</code>teilen sich alle Container das gleiche Netzwerk.&#8220;<br><strong>Bernd</strong> nickt: „Hab ich auch mal falsch gemacht. Der Container hat dann mit sich selbst geredet.&#8220;</p>



<p>Jetzt kommt der entscheidende Schritt: der&nbsp;<strong>Ausführungsbefehl</strong>.</p>



<ul class="wp-block-list">
<li><strong>Ausführungsbefehl</strong>&nbsp;setzen: <code>tunnel run --token &lt;DEIN_TOKEN_VON_OBEN_EINGEBEN&gt;</code></li>
</ul>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440086cba0&quot;}" data-wp-interactive="core/image" data-wp-key="69e440086cba0" class="wp-block-image aligncenter size-large is-resized wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="683" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-6-Container-Einstellungen-–-Ausfuehrungsbefehl-mit-Token-1024x683.png" alt="BILD 6 - Container-Einstellungen - Ausführungsbefehl mit Token" class="wp-image-644" style="aspect-ratio:1.4992854967554525;width:768px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-6-Container-Einstellungen-–-Ausfuehrungsbefehl-mit-Token-1024x683.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-6-Container-Einstellungen-–-Ausfuehrungsbefehl-mit-Token-300x200.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-6-Container-Einstellungen-–-Ausfuehrungsbefehl-mit-Token-768x512.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-6-Container-Einstellungen-–-Ausfuehrungsbefehl-mit-Token.png 1536w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 6 &#8211; Container-Einstellungen &#8211; Ausführungsbefehl mit Token</figcaption></figure>



<p>Ersetze&nbsp;<code>&lt;DEIN_TOKEN_VON_OBEN&gt;</code>&nbsp;mit dem langen Token, das du vorhin aus Cloudflare kopiert hast.</p>



<p><strong>Ulf</strong>: „Moment, ich soll jetzt diesen ellenlangen Code da reinpasten? Ohne Leerzeichen? Ohne dass ich mich vertippe?&#8220;<br><strong>Tanja</strong>: „Genau, deshalb: Kopieren, nicht abtippen. Ein einziger falscher Buchstabe, und der Container startet zwar, verbindet sich aber nicht mit Cloudflare.&#8220;</p>



<p>Klicke auf&nbsp;<strong>Weiter</strong>&nbsp;und dann auf&nbsp;<strong>Fertig</strong>. Der Container startet. Wenn alles geklappt hat, sollte er unter&nbsp;<strong>Container</strong>&nbsp;mit grünem Status laufen.</p>



<h5 class="wp-block-heading">Der Moment der Wahrheit</h5>



<p>Jetzt der Moment der Wahrheit: Öffne einen Browser und gib&nbsp;<code>https://n8n.deine-domain.de</code>&nbsp;ein. Du solltest die n8n-Anmeldeseite sehen über HTTPS, ohne dass du irgendwelche Zertifikate installiert hast.</p>



<p><strong>Ulf</strong> starrt auf den Bildschirm: „Das… das hat einfach funktioniert?&#8220;<br><strong>Tanja</strong> lächelnd: „Willkommen in der Welt der Cloudflare-Magie&#8220;.</p>



<p>Falls nicht, prüfe:</p>



<ul class="wp-block-list">
<li>Läuft der n8n-Container?</li>



<li>Läuft der Cloudflared-Container?</li>



<li>Steht im Tunnel die richtige URL (<code>localhost:5678</code>)?</li>



<li>Ist das Token korrekt eingegeben (ohne Leerzeichen am Anfang/Ende)?</li>
</ul>



<p><strong>Bernd</strong> kratzt sich am Kopf: „Bei mir stand da ‚Bad Gateway&#8216;. Ich hab dann einfach alles gelöscht und neu angefangen.&#8220;<br><strong>Tanja</strong>: „Das war vermutlich das Token. Einmal Leerzeichen zu viel, und Cloudflare versteht nur Bahnhof.&#8220;</p>



<h4 class="wp-block-heading">2.3 Schritt: n8n-Container auf die neue URL vorbereiten</h4>



<p>Bis hierhin funktioniert n8n zwar, aber es weiß noch nicht, dass es jetzt über eine neue URL erreichbar ist. Das mag nach einem Detailproblem klingen, ist aber entscheidend:&nbsp;<strong>Webhooks</strong>&nbsp;also Benachrichtigungen von externen Diensten wie Stripe, Telegram oder GitHub brauchen eine Rückmelde-Adresse. Wenn n8n denkt, es läuft unter&nbsp;<code>http://localhost:5678</code>, schickt es diese falsche Adresse an externe Dienste. Die können dann nicht zurückrufen.</p>



<p><strong>Ulf</strong>: „Moment, was sind Webhooks noch mal?&#8220;<br><strong>Tanja</strong>: „Stell dir vor, du bestellst eine Pizza, Du gibst dem Lieferdienst deine Adresse, damit er weiß, wo er klingeln soll. Ein Webhook ist genau das n8n gibt einem externen Dienst eine Adresse, an die dieser eine Nachricht schicken kann, wenn etwas passiert. Zum Beispiel: ‚Hey n8n, jemand hat gerade bezahlt, mach was mit dieser Info.'&#8220;<br><strong>Bernd</strong> nickt: „Ich hab mal einen Webhook eingerichtet. Der hat dann an&nbsp;<code>localhost</code>&nbsp;gesendet. Hat nicht funktioniert.&#8220;<br><strong>Tanja</strong> murmelt: „Überraschung&#8220;.</p>



<p>Du musst n8n also mitteilen: „Du bist jetzt unter&nbsp;<code>https://n8n.deine-domain.de</code>&nbsp;erreichbar.&#8220;<br>Wie du das machst, hängt davon ab, wie du n8n ursprünglich eingerichtet hast. Zwei Varianten:</p>



<h5 class="wp-block-heading">Variante A: Container manuell erstellt (über Container Manager)</h5>



<p>Wenn du den n8n-Container manuell über den Container Manager angelegt hast (nicht per Docker Compose), musst du die&nbsp;<strong>Umgebungsvariablen</strong>&nbsp;anpassen. Leider lässt Synology keine nachträgliche Bearbeitung von Containern zu – du musst den Container duplizieren.</p>



<ol class="wp-block-list">
<li>Gehe zu&nbsp;<strong>Container</strong>, wähle deinen n8n-Container aus und klicke auf&nbsp;<strong>Aktion → Stopp</strong>.</li>



<li>Klicke dann auf&nbsp;<strong>Aktion → Duplizieren</strong>.</li>



<li>Im neuen Container-Assistenten ergänze unter&nbsp;<strong>Umgebung</strong>&nbsp;folgende Variablen:<ul><li>N8N_HOST:&nbsp;<code>n8n.Deine_Domain.de</code></li><li>N8N_PROTOCOL:&nbsp;<code>https</code></li><li>WEBHOOK_URL:&nbsp;<code>https://n8n.Deine_Domain.de/</code></li></ul><strong>Ulf</strong>: „Warum steht da jetzt&nbsp;<code>https</code>?&#8220;<br><strong>Tanja</strong>: „Weil Cloudflare das HTTPS-Zertifikat übernimmt. Dein n8n selbst spricht zwar nur HTTP, aber nach außen – für die Welt – ist es HTTPS. Deshalb muss n8n wissen: ‚Hey, wenn du Webhooks registrierst, sag den Diensten, dass sie&nbsp;<code>https://</code>&nbsp;verwenden sollen, nicht&nbsp;<code>http://</code>.'&#8220;</li>
</ol>



<ul class="wp-block-list">
<li>Falls vorhanden:
<ul class="wp-block-list">
<li><code>N8N_SECURE_COOKIE=true</code>&nbsp;-&gt;&nbsp;<strong>entfernen</strong>, da HTTPS jetzt extern kommt<br>Da du jetzt ein echtes HTTPS-Zertifikat von Cloudflare hast, kannst du die Zeile&nbsp;<code>N8N_SECURE_COOKIE=true</code>&nbsp;stehen lassen (falls vorhanden) – oder sie setzen, falls sie noch fehlt. Das sorgt dafür, dass Cookies nur über verschlüsselte Verbindungen gesendet werden.</li>
</ul>
</li>
</ul>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440086d64c&quot;}" data-wp-interactive="core/image" data-wp-key="69e440086d64c" class="wp-block-image aligncenter size-large is-resized wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="683" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-7-Container-Umgebungsvariablen-mit-den-drei-neuen-Eintraegen-1-1024x683.png" alt="BILD 7 - Container-Umgebungsvariablen mit den drei neuen Einträgen N8N_HOST, N8N_PROTOCOL, WEBHOOK_URL" class="wp-image-651" style="aspect-ratio:1.4992854967554525;width:744px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-7-Container-Umgebungsvariablen-mit-den-drei-neuen-Eintraegen-1-1024x683.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-7-Container-Umgebungsvariablen-mit-den-drei-neuen-Eintraegen-1-300x200.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-7-Container-Umgebungsvariablen-mit-den-drei-neuen-Eintraegen-1-768x512.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-7-Container-Umgebungsvariablen-mit-den-drei-neuen-Eintraegen-1.png 1536w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 7 &#8211; Container-Umgebungsvariablen mit den drei neuen Einträgen N8N_HOST, N8N_PROTOCOL, WEBHOOK_URL</figcaption></figure>



<ol start="4" class="wp-block-list">
<li>Starte den neuen Container.</li>
</ol>



<h5 class="wp-block-heading">Variante B: n8n über Docker Compose (Projekt)</h5>



<p>Wenn du n8n per&nbsp;<strong>Docker Compose</strong>&nbsp;eingerichtet hast (eine detaillierte Beschreibung findest Du unter https://www.foundic.org/n8n-selbst-hosten-synology-nas-docker-installation/), ist die Anpassung eleganter:</p>



<ol class="wp-block-list">
<li>Stoppe das Projekt im Container Manager.</li>



<li>Wenn du den gleichen Projektnamen verwenden willst, lösche das alte Projekt.</li>



<li>Erstelle ein neues Projekt und wähle den gleichen Ordner-Pfad. Synology lädt automatisch die vorhandene&nbsp;<code>compose.yaml</code>.</li>



<li>Ergänze in der&nbsp;<code>compose.yaml</code>&nbsp;unter&nbsp;<code>services → n8n → environment</code>&nbsp;folgende drei Zeilen (nach&nbsp;<code>N8N_SECURE_COOKIE</code>)</li>



<li>Sowie ändere <code>N8N_SECURE_COOKIE</code> auf <code>true</code>, da HTTPS jetzt extern kommt</li>
</ol>



<pre class="wp-block-code"><code>    environment:
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=db
      - DB_POSTGRESDB_PORT=5432
      - DB_POSTGRESDB_DATABASE=n8n_db
      - DB_POSTGRESDB_USER=n8n_admin
      - DB_POSTGRESDB_PASSWORD=&lt;POSTGRES_PASSWORD&gt;
      - N8N_ENCRYPTION_KEY=&lt;DEIN_ENCRYPTION_KEY&gt;
 .    # --- NEUE VARIABLEN auf true ändern ---
      - N8N_SECURE_COOKIE=true
      # --- NEUE VARIABLEN FÜR CLOUDFLARE ---
      - N8N_HOST=n8n.Deine_Domain.de
      - N8N_PROTOCOL=https
      - WEBHOOK_URL=https://n8n.Deine_Domain.de/</code></pre>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440086dded&quot;}" data-wp-interactive="core/image" data-wp-key="69e440086dded" class="wp-block-image aligncenter size-large is-resized wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="683" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-8-compose.yaml-mit-markierten-Environment-Variablen-1024x683.png" alt="BILD 8 - compose.yaml mit markierten Environment-Variablen" class="wp-image-646" style="aspect-ratio:1.4992854967554525;width:834px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-8-compose.yaml-mit-markierten-Environment-Variablen-1024x683.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-8-compose.yaml-mit-markierten-Environment-Variablen-300x200.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-8-compose.yaml-mit-markierten-Environment-Variablen-768x512.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-8-compose.yaml-mit-markierten-Environment-Variablen.png 1536w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 8 &#8211; compose.yaml mit markierten Environment-Variablen</figcaption></figure>



<p><strong>Ulf</strong>: &#8222;Warum ist das jetzt eleganter?&#8220;<br><strong>Tanja</strong>: &#8222;Weil du die Datei einfach bearbeitest, statt den ganzen Container zu duplizieren. Du änderst drei Zeilen, speicherst, fertig. Kein Klickmarathon.&#8220;</p>



<p>Jetzt sollte alles wie gewünscht laufen. n8n ist über das Internet erreichbar,&nbsp;kennt seine eigene URL und kann Webhooks korrekt registrieren.</p>



<h4 class="wp-block-heading">2.4 Schritt: Zugriff über Cloudflare Zero Trust absichern</h4>



<p><strong>Ulf</strong>: „Moment mal&#8220;, sagt <strong>Ulf</strong>. „Jetzt ist mein n8n öffentlich im Internet? Kann da jetzt jeder drauf?&#8220;<br><strong>Tanja</strong>: „Genau. Jeder, der die URL kennt, kann theoretisch auf die Anmeldeseite zugreifen. n8n selbst hat zwar eine Benutzeranmeldung, aber es gibt keinen Schutz davor, dass jemand hundert Passwörter pro Minute ausprobiert oder nach Schwachstellen sucht.&#8220;<br><strong>Bernd</strong> nickt weise: „Hab ich auch mal erlebt. Irgendwann kamen die Login-Versuche schneller, als ich ‚Stopp&#8216; sagen konnte.&#8220;</p>



<p>Cloudflare bietet eine elegante Lösung:&nbsp;<strong>Access&nbsp;Control</strong>.&nbsp;Das ist eine zusätzliche Authentifizierungsschicht&nbsp;<em>vor</em>n8n. Wenn jemand <code>https://n8n.deine-domain.de</code> aufruft,&nbsp;prüft Cloudflare erst,&nbsp;ob die E-Mail-Adresse erlaubt ist – und schickt dann einen 6-stelligen Code per Mail. Erst mit dem richtigen Code kommt man überhaupt zur n8n-Anmeldeseite.</p>



<p><strong>Tanja</strong>: „Das ist wie ein Vorzimmer. Bevor du ins Büro kommst, musst du dich erst bei der Empfangsdame ausweisen.&#8220;</p>



<h5 class="wp-block-heading">Access Appliction einrichten</h5>



<p>Gehe auf der Cloudflare-Plattform zu&nbsp;<strong>Account&nbsp;Home -&gt; Zero Trust</strong> (nicht im Menü sondern rechts auf der Seite) <strong>-&gt; Go to Zero Trust -&gt; Access Control -&gt; Applications -&gt; Add an application</strong> -&gt; Typ:&nbsp;<strong>Self-hosted</strong></p>



<p>Einstellungen:</p>



<ul class="wp-block-list">
<li>Application Name:&nbsp;<code>n8n</code> (frei wählbar)</li>



<li>Session Duration:&nbsp;<strong>6 hours</strong> (so lange bleibt der Zugang gültig)</li>



<li>Subdomain:&nbsp;<code>n8n</code> (wie oben)</li>



<li>Domain: Wähle deine Domain aus</li>
</ul>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440086e683&quot;}" data-wp-interactive="core/image" data-wp-key="69e440086e683" class="wp-block-image aligncenter size-large is-resized wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="683" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-9-Cloudflare-Zero-Trust-Application-Setup-1024x683.png" alt="BILD 9 - Cloudflare Zero Trust - Application Setup" class="wp-image-647" style="aspect-ratio:1.4992854967554525;width:804px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-9-Cloudflare-Zero-Trust-Application-Setup-1024x683.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-9-Cloudflare-Zero-Trust-Application-Setup-300x200.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-9-Cloudflare-Zero-Trust-Application-Setup-768x512.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-9-Cloudflare-Zero-Trust-Application-Setup.png 1536w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 9 &#8211; Cloudflare Zero Trust &#8211; Application Setup</figcaption></figure>



<p><strong>Ulf</strong>: Was ist eine Session?&#8220;<br><strong>Tanja</strong>: „Eine Session ist wie ein Tagespass. Wenn du dich einmal authentifiziert hast, musst du nicht jedes Mal neu den Code eingeben. Nach 6 Stunden läuft der Pass ab, und du musst dich neu anmelden.&#8220;</p>



<p>Anschließend muss Du eine Policy anlegen -&gt; Add a policy</p>



<ul class="wp-block-list">
<li>Policy name: <code>n8n_zugriff</code>(frei wählbar)</li>



<li>Action: <code>Allow</code></li>



<li>Include -&gt; Selectore: eMails (auswählen),</li>



<li>Value: eMail-Adresse(n) eintragen</li>
</ul>



<p>Klicke auf&nbsp;<strong>Save&nbsp;policy</strong>&nbsp;und dann auf&nbsp;<strong>Save&nbsp;application</strong></p>



<h5 class="wp-block-heading">Wichtig: Webhooks ausnehmen</h5>



<p><strong>Ulf</strong>: „Warte mal, wenn jetzt jeder diesen Code braucht,was ist mit den Webhooks? Die kommen doch von außen?&#8220;<br><strong>Tanja</strong>: „Genau das Problem. Wenn Stripe, Telegram oder GitHub einen Webhook an n8n schicken, werden sie von Cloudflare Access blockiert. Die haben ja keine E-Mail-Adresse und können keinen Code eingeben.&#8220;<br><strong>Bernd</strong> nickt: „Bei mir hat Stripe dann irgendwann aufgegeben. Dachte, mein Server wär tot.&#8220;</p>



<p>Die Lösung: Du legst eine&nbsp;<strong>zweite Subdomain</strong>&nbsp;an, nur für Webhooks. Die schützt du anders.</p>



<p>Gehe zurück zu&nbsp;<strong>Networking&nbsp;→ Tunnels</strong>,&nbsp;öffne deinen Tunnel und füge eine zweite Route hinzu:&nbsp;<br>&#8211;&nbsp;<strong>Subdomain</strong>:&nbsp;<code>n8n-webhook</code>&nbsp;</p>



<ul class="wp-block-list">
<li><strong>Domain</strong>:&nbsp;Deine Domain&nbsp;<br>&#8211;&nbsp;<strong>Type</strong>:&nbsp;<code>HTTP</code>&nbsp;<br>&#8211;&nbsp;<strong>URL</strong>:&nbsp;<code>localhost:5678</code>&nbsp;`</li>
</ul>



<p>Speichere das. Jetzt ist n8n unter zwei URLs erreichbar:&nbsp;</p>



<ul class="wp-block-list">
<li><code>https://n8n.deine-domain.de</code>(geschützt durch Access,&nbsp;für dich)<br>&#8211;&nbsp;<code>https://n8n-webhook.deine-domain.de</code> (öffentlich zugänglich,&nbsp;für Webhooks)&nbsp;</li>
</ul>



<p><strong>Ulf</strong>: „Ist das nicht unsicher?&#8220;<br><strong>Tanja</strong>: „Ein bisschen. Aber die Webhook-URL kennt nur, wer sie von dir bekommt. Und externe Dienste validieren oft ihre eigenen Webhooks, Stripe schickt zum Beispiel eine Signatur mit, die du in n8n prüfen kannst.&#8220;</p>



<p>Für die Webhook-URL musst du&nbsp;<em>keine</em>&nbsp;Access Policy anlegen. Oder du legst eine an,&nbsp;die nur den Pfad <code>/webhook/</code> durchlässt (je nachdem,&nbsp;wie paranoid du bist).&nbsp;In n8n selbst musst du dann bei jedem Webhook-Trigger darauf achten,&nbsp;dass du die&nbsp;<strong>Webhook-Subdomain</strong>&nbsp;verwendest,&nbsp;also:&nbsp;<code>https://n8n-webhook.deine-domain.de/webhook/...</code></p>



<h5 class="wp-block-heading">Der finale Test</h5>



<p>Wenn du nun&nbsp;<code>https://n8n.deine-domain.de</code>&nbsp;aufrufst, gelangst du nicht direkt auf den n8n-Login, sondern Cloudflare schiebt eine&nbsp;<strong>Cloudflare Access</strong>-Seite dazwischen, auf der du eine deiner bei Cloudflare hinterlegten E-Mail-Adressen eingibst. An diese bekommst du dann einen 6-stelligen Code gesendet, den du zur Freigabe benötigst.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440086efc9&quot;}" data-wp-interactive="core/image" data-wp-key="69e440086efc9" class="wp-block-image aligncenter size-large is-resized wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="683" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-10-Cloudflare-Zero-Trust-Access-Seite-1024x683.png" alt="BILD 10 - Cloudflare Zero Trust - Access Seite" class="wp-image-756" style="aspect-ratio:1.2689097289688125;width:740px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-10-Cloudflare-Zero-Trust-Access-Seite-1024x683.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-10-Cloudflare-Zero-Trust-Access-Seite-300x200.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-10-Cloudflare-Zero-Trust-Access-Seite-768x512.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-10-Cloudflare-Zero-Trust-Access-Seite.png 1536w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 10 &#8211; Cloudflare Zero Trust &#8211; Access Seite</figcaption></figure>



<p><strong>Ulf</strong>: „Das ist ja wie beim Online-Banking&#8220;<br><strong>Tanja</strong>: „Genau, und genau deshalb ist es sicher.&#8220;</p>



<h3 class="wp-block-heading">3 Fazit</h3>



<p>Du hast ein n8n, das über das Internet erreichbar ist, ohne offene Ports, ohne manuelle SSL-Zertifikate, ohne dass du deine Router-Konfiguration auch nur angeschaut hast. Cloudflare sitzt als Türsteher davor, filtert Bots, schützt vor DDoS und lässt nur dich rein.</p>



<p>Webhooks funktionieren, externe Dienste können mit n8n sprechen, und du kannst von überall auf deine Automatisierungen zugreifen, vom Café, vom Flughafen, vom Sofa aus.</p>



<p>Das ist der Moment, in dem aus einem lokalen Experiment eine brauchbare Infrastruktur wird. Keine Enterprise-Lösung, klar – aber eine, die zuverlässig läuft, ohne dass du dich jede Woche um irgendwelche Updates oder Sicherheitslücken kümmern musst.</p>



<p><strong>Ulf</strong> lehnt sich zurück. „Okay, ich geb&#8217;s zu. Das war einfacher, als ich dachte.&#8220;<br><strong>Bernd</strong> nickt. „Ich hab immer noch keine Ahnung, was ich da gemacht hab. Aber es läuft.&#8220;<br><strong>Tanja</strong> lächelt. „Genau das ist der Punkt.&#8220;</p>



<p>Cloudflare macht das Hosting nicht überflüssig. Aber es macht es zugänglich auch für Leute, die keine Systemadministratoren sind, sondern einfach nur Workflows bauen wollen, die funktionieren.</p>



<p>Hast du Verbesserungsvorschläge für diese Anleitung oder foundic.org? Ich freue mich über dein Feedback in den Kommentaren!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.foundic.org/de/n8n-cloudflare-tunnel-synology-nas/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>n8n selber hosten &#8211; n8n Installation auf Synology NAS (Diskstation DS1621+) optional mit PostgreSQL</title>
		<link>https://www.foundic.org/de/n8n-selbst-hosten-synology-nas-docker-installation/</link>
					<comments>https://www.foundic.org/de/n8n-selbst-hosten-synology-nas-docker-installation/#comments</comments>
		
		<dc:creator><![CDATA[Michael Müller]]></dc:creator>
		<pubDate>Sun, 01 Feb 2026 19:28:00 +0000</pubDate>
				<category><![CDATA[Projekte]]></category>
		<guid isPermaLink="false">https://www.foundic.org/?p=269</guid>

					<description><![CDATA[Wer n8n selber hosten möchte, findet hier die komplette Schritt-für-Schritt-Anleitung. Automatisierung galt lange als Spielfeld großer Unternehmen: teuer, komplex, schwer kontrollierbar.Mit&#160;n8n&#160;hat sich das verändert. Plötzlich lässt sich Enterprise-Logik auf einem Gerät betreiben, das bei vielen ohnehin im Keller oder Arbeitszimmer steht: einer&#160;Synology DiskStation. In diesem Beitrag zeige ich Schritt für Schritt, wie du&#160;n8n selbst hostest&#160;– [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Wer n8n selber hosten möchte, findet hier die komplette Schritt-für-Schritt-Anleitung. Automatisierung galt lange als Spielfeld großer Unternehmen: teuer, komplex, schwer kontrollierbar.<br>Mit&nbsp;<strong><a href="https://n8n.io/" target="_blank" rel="noopener">n8n</a></strong>&nbsp;hat sich das verändert. Plötzlich lässt sich Enterprise-Logik auf einem Gerät betreiben, das bei vielen ohnehin im Keller oder Arbeitszimmer steht: einer&nbsp;<strong><a href="https://www.synology.com/" target="_blank" rel="noopener">Synology DiskStation</a></strong>.</p>



<p>In diesem Beitrag zeige ich Schritt für Schritt, wie du&nbsp;<strong>n8n selbst hostest</strong>&nbsp;– sauber gekapselt in Containern, optional mit einer stabilen PostgreSQL-Datenbank. Keine Vorkenntnisse nötig, nur Neugier.</p>



<p><strong>Um diese Anleitung verständlicher zu machen, begleiten dich drei Personen:</strong><br>Die typischen Büro-Charaktere: Die kompetente IT-Kollegin, der selbsternannte Experte und der ehrliche Anfänger. Diese drei Perspektiven helfen dir, typische Stolperfallen zu erkennen und n8n wirklich zu verstehen.</p>



<p><strong>Tanja</strong>&nbsp;ist die IT-Expertin. Sie weiß, wie n8n funktioniert, erklärt geduldig und strukturiert – und lässt sich von schlechten Ratschlägen nicht aus der Ruhe bringen. Wenn du eine Frage hast, hat Tanja die Antwort.<br><strong>Bernd</strong>&nbsp;ist der selbsternannte „Experte“, der alles besser weiß – und meistens falsch liegt. Seine Abkürzungen und sein Halbwissen führen regelmäßig zu Problemen. Er steht für alle gefährlichen Mythen und schlechten Praktiken, die du vermeiden solltest.<br><strong>Ulf</strong>&nbsp;ist der Lernende, genau wie du. Er stellt die Fragen, die dir im Kopf herumschwirren, und braucht manchmal einen Vergleich aus dem Alltag, um IT zu verstehen. Wenn Ulf etwas nicht versteht, ist das völlig in Ordnung – dafür ist Tanja da.</p>



<p><strong>&#8222;Und… Action!&#8220;</strong></p>



<p>Montagmorgen, 8:47 Uhr. Bernd betritt das Büro mit zwei Kaffees und einem selbstzufriedenen Grinsen.<br><strong>Bernd</strong>: „Leute, ich hab&#8217;s gecheckt. Automatisierung ist die Zukunft. Hab gestern Abend so ein Tool entdeckt – n8n oder so. Läuft auf meinem Laptop. Hab schon drei Workflows gebaut. Einer davon sortiert meine E-Mails. Na ja, er hat alle in den Spam verschoben, aber das Prinzip steht.&#8220;<br>Tanja blickt nicht mal von ihrem Bildschirm auf.<br><strong>Tanja:</strong> „Bernd, läuft das Tool noch?&#8220;<br><strong>Bernd:</strong> „Äh… hab den Laptop zugemacht.&#8220;<br><strong>Tanja:</strong> „Dann läuft&#8217;s nicht mehr.&#8220;<br><strong>Bernd:</strong> „Aber… ich hab doch auf Speichern geklickt!&#8220;<br><strong>Ulf</strong> gähnt. „Alter, können wir das nicht einfach in die Cloud packen? So wie bei Netflix? Immer an, immer da.&#8220;<br><strong>Tanja</strong> dreht sich um. „Können wir. Kostet dann halt 20 bis 50 Euro im Monat, je nachdem wie viele Workflows du baust. Oder…&#8220; – sie zeigt auf ein unauffälliges Kästchen unter ihrem Schreibtisch – „…du nimmst das Ding, das bei dir eh schon läuft und Staub fängt.&#8220;<br>„Meine Synology?&#8220; <strong>Ulf</strong> schaut skeptisch. „Die kann doch nur Filme speichern.&#8220;<br><strong>Tanja:</strong> „Filme, Backups, Fotos… und jetzt eben auch deine Automatisierung. Kostet dich keinen Cent extra. Läuft 24/7. Und deine Daten bleiben bei dir, nicht bei irgendeinem Anbieter, der sie sich für Werbung anschaut.&#8220;<br><strong>Bernd</strong> unterbricht: „Klingt kompliziert.&#8220;<br>„Ist es nicht&#8220;, sagt <strong>Tanja</strong>. „Du klickst dich durch ein paar Einstellungen, startest zwei Container, fertig. Dauert keine halbe Stunde.&#8220;<br><strong>Bernd:</strong> „Container? Wie… Schiffscontainer?&#8220;<br><strong>Ulf</strong> lacht. „Bro, die hat grade gesagt &#8218;halbe Stunde&#8216;. Das kriegen sogar wir hin.&#8220;</p>



<h2 class="wp-block-heading">1 Was ist n8n?</h2>



<p><strong><a href="https://n8n.io/" target="_blank" rel="noopener">n8n</a></strong>&nbsp;ist eine&nbsp;<strong>Open-Source-Plattform für Workflow-Automatisierung</strong>. Stell dir vor, du baust mit Legosteinen eine Maschine – nur dass die Bausteine keine Räder oder Motoren sind, sondern Apps, Dienste und Daten.<br>Du verbindest zum Beispiel:</p>



<ul class="wp-block-list">
<li>Gmail mit Google Sheets</li>



<li>Eine Wetter-API mit Slack</li>



<li>Einen Webhook mit einer KI, die dir automatisch E-Mails zusammenfasst</li>
</ul>



<p>Das Ganze passiert über eine&nbsp;<strong>visuelle Oberfläche</strong>: Du ziehst Kästen auf eine Arbeitsfläche, verbindest sie mit Pfeilen, stellst Bedingungen ein. Fertig ist der Workflow.<br><strong>Der entscheidende Unterschied zu anderen Tools:</strong><br>n8n ist&nbsp;<strong>Low-Code</strong>, aber nicht&nbsp;<strong>No-Code</strong>. Das heißt:</p>



<ul class="wp-block-list">
<li>Einsteiger klicken ihre Workflows zusammen, ohne eine Zeile Code zu schreiben.</li>



<li>Fortgeschrittene können jederzeit JavaScript oder Python einbauen, wenn&#8217;s kompliziert wird.</li>



<li>Du kannst&nbsp;<strong>KI-Modelle</strong>&nbsp;direkt einbinden OpenAI, Anthropic Claude, oder sogar lokale Modelle über Ollama.</li>
</ul>



<p><strong>Typische Einsätze:</strong></p>



<ul class="wp-block-list">
<li>E-Mails automatisch verarbeiten (z. B. Rechnungen rausfiltern und in eine Datenbank packen)</li>



<li>APIs miteinander verbinden (z. B. neue Trello-Karten automatisch in Notion übertragen)</li>



<li>Dateien analysieren, transformieren, weiterleiten (z. B. PDFs automatisch per KI zusammenfassen lassen)</li>



<li>Benachrichtigungen, Reports, Webhooks orchestrieren<br>Und das Wichtigste:&nbsp;<strong>n8n gehört dir.</strong>&nbsp;Keine fremde Cloud. Kein Lock-in. Deine Daten, deine Kontrolle.</li>
</ul>



<p><strong>Ulf:</strong>&nbsp;„Okay, aber warum sollte ich mir den Stress antun? Es gibt doch bestimmt auch einfachere Tools.&#8220;<br><strong>Tanja:</strong>&nbsp;„Gibt es. Zapier zum Beispiel. Macht ungefähr das Gleiche. Kostet dich aber ab einem gewissen Punkt richtig Geld – 20, 50, 100 Euro im Monat, je nachdem wie viele Workflows du baust und wie oft die laufen. n8n kostet dich: nichts. Null Euro. Läuft auf deiner eigenen Hardware.&#8220;<br><strong>Bernd:</strong>&nbsp;„Und wenn ich die Hardware nicht habe?&#8220;<br><strong>Tanja:</strong>&nbsp;„Dann mietest du dir einen Server für 5 Euro im Monat. Immer noch billiger. Aber die meisten von uns haben schon eine Synology rumstehen. Die ist perfekt dafür.&#8220;<br><strong>Ulf:</strong>&nbsp;„Was kann n8n denn, was Zapier nicht kann?&#8220;<br><strong>Tanja:</strong>&nbsp;„Alles anpassen. Eigene Nodes schreiben. Lokale Datenbanken anbinden. KI-Modelle laufen lassen, die nicht in der Cloud hängen. Und du kannst die Workflows als Code exportieren und weitergeben – Open Source eben.&#8220;</p>



<h3 class="wp-block-heading">1.1 Erweiterte Funktionen und Integrationsmöglichkeiten</h3>



<p>n8n ist kein einfaches &#8222;Wenn-Dann&#8220;-Tool. Es ist eine&nbsp;<strong>echte Automatisierungs-Plattform</strong>&nbsp;mit über&nbsp;<strong>400 vorgefertigten Integrationen</strong>:</p>



<ul class="wp-block-list">
<li><strong>Apps und Dienste</strong>: Google Sheets, Slack, Notion, GitHub, Trello, Airtable, WordPress…</li>



<li><strong>Datenbanken</strong>: MySQL, PostgreSQL, MongoDB, Redis</li>



<li><strong>KI-Dienste</strong>: OpenAI, Anthropic Claude, Hugging Face, Ollama (für lokale Modelle)</li>



<li><strong>Trigger-Typen</strong>:
<ul class="wp-block-list">
<li>Zeitbasiert (Cron-Jobs): „Jeden Montag um 9 Uhr&#8220;</li>



<li>Webhooks: „Sobald jemand ein Formular abschickt&#8220;</li>



<li>Manuell: „Nur wenn ich auf &#8218;Start&#8216; drücke&#8220;</li>



<li>Externe Ereignisse: „Wenn ein neuer Eintrag in der Datenbank auftaucht&#8220;<br>Das Debugging läuft&nbsp;<strong>in Echtzeit</strong>: Du siehst genau, welche Daten in jeden Baustein reingehen und wieder rauskommen. Wenn ein Workflow nicht funktioniert, kannst du jeden einzelnen Schritt nachvollziehen.<br>Und falls eine Integration fehlt? n8n hat eine&nbsp;<strong>riesige Community</strong>&nbsp;mit tausenden selbst gebauten Nodes. Und es gibt eine&nbsp;<strong>Template-Datenbank</strong>: Fertige Workflows, die du einfach per Copy &amp; Paste importieren kannst. Brauchst du einen PDF-Zusammenfasser mit KI? Gibt&#8217;s schon. E-Mail-Router? Auch da. CRM-Synchronisation? Läuft.<br>Du musst nicht alles selbst bauen. Du kannst auf vorhandene Lösungen aufbauen.</li>
</ul>
</li>
</ul>



<p><strong>Bernd:</strong>&nbsp;„Moment. Wenn das so einfach ist, warum macht das nicht jeder?&#8220;<br><strong>Tanja:</strong>&nbsp;„Weil die meisten denken, Automatisierung ist kompliziert. Und weil viele nicht wissen, dass ihre NAS mehr kann als Filme speichern.&#8220;<br><strong>Ulf:</strong>&nbsp;„Aber was mache ich konkret damit? Gib mir ein Beispiel, das nicht nerdy klingt.&#8220;<br><strong>Tanja:</strong>&nbsp;„Okay. Du bekommst jeden Tag E-Mails von Kunden mit Anfragen. Manche davon sind dringend, manche nicht. n8n liest die E-Mails, analysiert sie mit einer KI, sortiert sie nach Priorität und schickt dir nur die wichtigen als Push-Nachricht aufs Handy. Der Rest landet automatisch in Notion mit einer Zusammenfassung.&#8220;<br><strong>Ulf:</strong>&nbsp;„Das geht?&#8220;<br><strong>Tanja:</strong>&nbsp;„Das geht. Und dauert ungefähr 15 Minuten, wenn du das Template aus der Community nimmst.&#8220;</p>



<h3 class="wp-block-heading">1.2 Praxisbeispiele für n8n-Workflows</h3>



<p>Damit du dir besser vorstellen kannst, was n8n in der Praxis leistet, hier ein paar konkrete Szenarien:</p>



<ol class="wp-block-list">
<li>Synchronisation zwischen Systemen: Du pflegst Kundendaten in einem CRM (z. B. HubSpot), willst sie aber auch in Google Sheets haben, weil dein Team dort besser arbeitet. n8n synchronisiert beide Systeme automatisch: Neue Einträge im CRM landen in der Tabelle, Änderungen in der Tabelle werden zurück ins CRM geschrieben.</li>



<li>Automatisierte Benachrichtigungen:&nbsp;Sobald ein bestimmtes Ereignis eintritt – ein neuer Lead, ein abgeschlossener Deal, ein Fehler in einem System – schickt n8n dir eine Nachricht. Slack, E-Mail, Telegram, was auch immer du nutzt.</li>



<li>KI-gestützte Datenverarbeitung:&nbsp;Du lädst ein Dokument hoch. n8n schickt es an ein KI-Modell (z. B. Claude), lässt es zusammenfassen, extrahiert wichtige Fakten und speichert das Ergebnis in einer Datenbank. Alles automatisch, sobald die Datei landet.</li>



<li>Content-Verwaltung:&nbsp;Neue Blogposts aus einem RSS-Feed werden automatisch in Notion gespeichert, analysiert und mit passenden Tags versehen. Am Ende der Woche bekommst du eine Zusammenfassung der interessantesten Artikel.<br>Das sind keine Science-Fiction-Szenarien. Das sind Workflows, die Leute heute schon nutzen. Und du kannst sie dir fertig aus der Community holen.</li>
</ol>



<h2 class="wp-block-heading">2 Warum n8n selber hosten?</h2>



<p>Selbsthosting ist kein Selbstzweck. Es ist eine&nbsp;<strong>bewusste Entscheidung</strong>&nbsp;mit klaren Vorteilen:</p>



<ol class="wp-block-list">
<li>Datenhoheit:&nbsp;Deine Workflows, deine Zugangsdaten, deine Logs – alles bleibt lokal. Kein Drittanbieter kann mitlesen, keine Cloud-Firma hat Zugriff. Wenn du sensible Daten verarbeitest (Kundendaten, Finanzen, interne Prozesse), ist das ein echter Vorteil.</li>



<li>Kostenkontrolle:&nbsp;Keine nutzungsabhängigen Preise. Kein „Du hast dein Limit erreicht, zahl jetzt mehr&#8220;-Popup. Du zahlst einmal für die Hardware (die du eh schon hast) und dann: nichts mehr.</li>



<li>Erweiterbarkeit:&nbsp;Du kannst eigene Datenbanken anbinden, lokale KI-Modelle laufen lassen, eigene Skripte schreiben. Bei Cloud-Diensten bist du auf das beschränkt, was der Anbieter dir gibt.</li>



<li>Lernkurve:&nbsp;Du verstehst,&nbsp;<em>wie</em>&nbsp;Systeme wirklich laufen. Nicht nur „Ich klicke hier, es passiert Magie&#8220;, sondern: „Ich verstehe, was ein Container ist, wie Datenbanken funktionieren, wie Netzwerke kommunizieren.&#8220; Das ist Wissen, das dir langfristig hilft.<br>Und:&nbsp;Eine Synology NAS eignet sich dafür überraschend gut.&nbsp;Zuverlässig, stromsparend, immer verfügbar. Wahrscheinlich läuft sie bei dir eh schon 24/7 für Backups und Medien. Jetzt machst du einfach&nbsp;<em>mehr</em>&nbsp;daraus.</li>
</ol>



<p><strong>Bernd:</strong>&nbsp;„Aber ich hab keine Lust, mich mit Servern rumzuschlagen. Ich will einfach nur, dass es funktioniert.&#8220;<br><strong>Tanja:</strong>&nbsp;„Dann nimm die Cloud-Variante von n8n. Kostet dich 20 Euro im Monat, funktioniert sofort. Aber: Du gibst Kontrolle ab. Und du zahlst für jede Ausführung, jeden Workflow, jede Integration.&#8220;<br><strong>Ulf:</strong>&nbsp;„Und wenn ich&#8217;s selbst hoste, zahl ich nix?&#8220;<br><strong>Tanja:</strong>&nbsp;„Du zahlst Strom. Vielleicht 2 bis 3 Euro im Monat, wenn die NAS eh läuft. Und einmalig ein bisschen Zeit für die Einrichtung. Danach: läuft.&#8220;<br><strong>Bernd:</strong>&nbsp;„Wie viel Zeit?&#8220;<br><strong>Tanja:</strong>&nbsp;„Wenn du alles zum ersten Mal machst? Eine Stunde. Wenn du dieser Anleitung folgst? Dreißig Minuten.&#8220;<br><strong>Ulf:</strong>&nbsp;„Okay. Und was brauche ich dafür?&#8220;</p>



<h3 class="wp-block-heading">2.1 n8n selber hosten vs. gehostete Lösung</h3>



<p>Lass uns das kurz gegenüberstellen, damit du eine informierte Entscheidung treffen kannst:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Kriterium</th><th>Self-Hosting (diese Anleitung)</th><th>n8n Cloud (gehostet)</th></tr></thead><tbody><tr><td><strong>Kosten</strong></td><td>~2–3 € Strom/Monat (wenn NAS eh läuft)</td><td>Ab 20 €/Monat, steigt mit Nutzung</td></tr><tr><td><strong>Datenkontrolle</strong></td><td>100 % bei dir</td><td>Bei n8n Inc. gespeichert</td></tr><tr><td><strong>Wartung</strong></td><td>Du kümmerst dich selbst</td><td>Wird für dich gemacht</td></tr><tr><td><strong>Erweiterbarkeit</strong></td><td>Unbegrenzt (eigene Nodes, lokale Modelle)</td><td>Auf Cloud-Features beschränkt</td></tr><tr><td><strong>Setup-Zeit</strong></td><td>30–60 Minuten (einmalig)</td><td>5 Minuten (Anmeldung)</td></tr><tr><td><strong>Lerneffekt</strong></td><td>Hoch (du verstehst, wie&#8217;s läuft)</td><td>Gering (Black Box)</td></tr></tbody></table></figure>



<p>Für viele ist die Cloud-Variante der schnellste Einstieg. Aber langfristig und gerade wenn du mehr Kontrolle willst ist Self-Hosting die bessere Wahl.</p>



<h3 class="wp-block-heading">2.2 Voraussetzungen</h3>



<p>Diese Anleitung basiert auf folgender Ausstattung:</p>



<ul class="wp-block-list">
<li>Synology DiskStation DS1621+</li>



<li>CPU-Architektur:&nbsp;x86_64 (Intel/AMD)</li>



<li>DSM 7.2 oder neuer</li>



<li>Mindestens&nbsp;2 GB RAM&nbsp;(empfohlen:&nbsp;4 GB oder mehr)<br>Die Schritte funktionieren auch auf anderen x86-Synology-Modellen. Wenn du eine ältere oder ARM-basierte NAS hast, kann es sein, dass bestimmte Docker-Images nicht laufen. Prüf im Zweifel vorher die Kompatibilität.<br>Du brauchst&nbsp;<strong>keine</strong>&nbsp;Vorkenntnisse in Linux, Datenbanken oder Netzwerktechnik. Du musst nur bereit sein, ein paar Einstellungen durchzuklicken und zu verstehen, was du da tust.</li>
</ul>



<p><strong>Ulf:</strong>&nbsp;„Moment. Was ist x86? Ist das wichtig?&#8220;<br><strong>Tanja:</strong>&nbsp;„Das ist die Prozessor-Architektur. Also die Sprache, die dein Chip versteht. Die meisten Synology-Modelle mit Intel- oder AMD-Prozessoren sind x86. Wenn du eine ganz alte oder billige NAS hast, kann es sein, dass sie ARM nutzt – dann laufen manche Docker-Images nicht.&#8220;<br><strong>Bernd:</strong>&nbsp;„Woher weiß ich, was ich habe?&#8220;<br><strong>Tanja:</strong>&nbsp;„Systemsteuerung → Info-Center. Steht da. Oder einfach das Modell googeln.&#8220;<br><strong>Ulf:</strong>&nbsp;„Und die 4 GB RAM – ist das Pflicht?&#8220;<br><strong>Tanja:</strong>&nbsp;„Nein. n8n läuft auch mit 2 GB. Aber wenn du PostgreSQL nutzen willst – die bessere Datenbank – dann solltest du 4 GB haben. Sonst wird&#8217;s eng.&#8220;</p>



<h3 class="wp-block-heading">2.2 Grundbegriffe (kurz erklärt)</h3>



<p>Bevor wir loslegen, klären wir zwei Begriffe, die dir immer wieder begegnen werden:</p>



<ul class="wp-block-list">
<li><strong>Docker / Container</strong>&nbsp;Stell dir einen Container vor wie eine&nbsp;<strong>Werkzeugkiste</strong>. In der Kiste ist alles drin, was ein Programm braucht: Code, Bibliotheken, Einstellungen. Du kannst die Kiste öffnen, das Programm läuft. Du kannst sie schließen, das Programm stoppt. Und vor allem: Die Kiste ist&nbsp;sauber getrennt&nbsp;vom Rest deines Systems. Wenn in der Kiste was kaputtgeht, bleibt der Rest unbeschädigt.</li>
</ul>



<p>Docker ist das System, das diese Kisten verwaltet. Auf der Synology heißt es jetzt&nbsp;<strong>Container Manager</strong>.</p>



<ul class="wp-block-list">
<li><strong>Volume</strong>&nbsp;Ein Volume ist ein&nbsp;gemappter Ordner. Stell dir vor, du arbeitest in deinem Büro (dem Container), aber alle wichtigen Unterlagen liegen in einem Aktenschrank im Keller (der NAS). Der Container greift auf diesen Ordner zu, liest und schreibt Dateien aber die Dateien selbst bleiben außerhalb des Containers gespeichert.</li>
</ul>



<p>Warum ist das wichtig? Weil Container&nbsp;<strong>vergesslich</strong>&nbsp;sind. Wenn du einen Container löschst, sind alle Daten darin weg. Aber wenn die Daten in einem Volume liegen, bleiben sie erhalten. Du kannst den Container neu starten, updaten, löschen die Daten sind sicher.</p>



<p><strong>Bernd:</strong>&nbsp;„Also ist ein Container wie eine virtuelle Maschine?&#8220;<br><strong>Tanja:</strong>&nbsp;„Ähnlich, aber viel schlanker. Eine VM simuliert einen kompletten Computer inklusive Betriebssystem. Ein Container teilt sich das Betriebssystem mit dem Host, ist aber trotzdem isoliert. Deshalb startet ein Container in Sekunden, eine VM braucht Minuten.&#8220;<br><strong>Ulf:</strong>&nbsp;„Und wenn ich den Container lösche, sind meine Workflows weg?&#8220;<br><strong>Tanja:</strong>&nbsp;„Nur wenn du kein Volume nutzt. Deshalb mappen wir gleich einen Ordner auf der NAS. Dann bleiben deine Daten auch nach einem Neustart oder Update erhalten.&#8220;</p>



<h3 class="wp-block-heading">2.4 SQLite oder PostgreSQL? Eine bewusste Entscheidung</h3>



<p>n8n kann mit zwei verschiedenen Datenbanken arbeiten:</p>



<ul class="wp-block-list">
<li><strong><a href="https://sqlite.org" target="_blank" rel="noopener">SQLite</a></strong>&nbsp;ist eine&nbsp;<strong>eingebettete Datenbank</strong>. Sie wird automatisch mit n8n installiert, braucht keine zusätzliche Konfiguration. Alles läuft in einer einzigen Datei. Einfach, unkompliziert, sofort startklar. Wann nutzt du SQLite?
<ul class="wp-block-list">
<li>Wenn du n8n zum ersten Mal ausprobierst</li>



<li>Wenn du nur ein bis fünf einfache Workflows hast</li>



<li>Wenn du keine Lust auf zusätzliche Komplexität hast</li>



<li>Wenn du n8n nur privat nutzt</li>
</ul>
</li>



<li><strong><strong><a href="https://www.postgresql.org" target="_blank" rel="noopener">PostgreSQL</a></strong></strong>&nbsp;ist eine&nbsp;<strong>ausgewachsene relationale Datenbank</strong>. Sie läuft in einem eigenen Container, braucht eigene Einstellungen, eigene Ports. Klingt kompliziert – ist es aber nicht. Und sie ist&nbsp;stabiler, schneller und besser&nbsp;für den produktiven Einsatz. Wann nutzt du PostgreSQL?
<ul class="wp-block-list">
<li>Wenn du n8n ernsthaft nutzen willst (mehrere Workflows, zeitgesteuerte Prozesse)</li>



<li>Wenn du langfristig Daten speichern und analysieren willst</li>



<li>Wenn du mindestens 4 GB RAM hast</li>



<li>Wenn du irgendwann skalieren willst (mehr Workflows, mehr Daten, mehr Komplexität)</li>
</ul>
</li>
</ul>



<p><strong>Faustregel:</strong>&nbsp;Unter 4 GB RAM → SQLite ab 4 GB RAM → PostgreSQL<br>Diese Anleitung zeigt dir&nbsp;beide Wege. Du entscheidest. Und du kannst später jederzeit wechseln (mit etwas Aufwand, aber es geht).</p>



<p><strong>Ulf:</strong>&nbsp;„Also wenn ich&#8217;s einfach halten will, nehme ich SQLite?&#8220;<br><strong>Tanja:</strong>&nbsp;„Genau. Läuft sofort, keine zusätzliche Konfiguration. Aber wenn du merkst, dass n8n langsamer wird oder du viele Workflows hast, wechselst du zu PostgreSQL.&#8220;<br><strong>Bernd:</strong>&nbsp;„Ich nehme natürlich PostgreSQL. Klingt professioneller.&#8220;<br><strong>Tanja:</strong>&nbsp;„Bernd, du hast 2 GB RAM.&#8220;<br><strong>Bernd:</strong>&nbsp;„Ach, das reicht schon.&#8220;<br><strong>Tanja:</strong>&nbsp;„Nein. Das wird Probleme geben. Nimm SQLite. Oder rüste das RAM auf.&#8220;<br><strong>Ulf:</strong>&nbsp;„Ich hab 8 GB. Was nehme ich?&#8220;<br><strong>Tanja:</strong>&nbsp;„PostgreSQL. Kein Zweifel.&#8220;</p>



<h2 class="wp-block-heading"> 3 Die Installationsschritte von n8n</h2>



<p>Jetzt wird&#8217;s konkret. Wir gehen&nbsp;<strong>Schritt für Schritt</strong>&nbsp;durch die Installation. Du musst nichts überspringen, nichts raten, nichts voraussetzen. Einfach mitmachen.</p>



<p><strong>Der Überblick:</strong></p>



<ol class="wp-block-list">
<li>Vorbereitung der DiskStation</li>



<li>PostgreSQL Image herunterladen <em>(optional, nur wenn du PostgreSQL nutzt)</em></li>



<li>PostgreSQL Datenbank einrichten <em>(optional)</em></li>



<li>Projekt-Variante mit Docker Compose&nbsp;<em>(Alternative für Fortgeschrittene)</em></li>



<li>n8n Image herunterladen</li>



<li>n8n Container konfigurieren</li>



<li>Erster Login in n8n</li>
</ol>



<p>Wenn du&nbsp;<strong>SQLite</strong>&nbsp;nutzt, überspringst du die Schritte 2 und 3. Wenn du&nbsp;<strong>Docker Compose</strong>&nbsp;nutzt, überspringst du 2, 3, 5 und 6 und springst direkt zu Schritt 4.<br>Klingt kompliziert? Ist es nicht. Los geht&#8217;s.</p>



<h3 class="wp-block-heading">3.1 Vorbereitung der DiskStation</h3>



<p>Bevor wir n8n starten können, muss die NAS vorbereitet werden. Drei Dinge sind wichtig: den Container Manager installieren, Ordner für die Daten anlegen, Berechtigungen setzen.</p>



<h4 class="wp-block-heading">Container Manager installieren</h4>



<p>Öffne das&nbsp;<strong>Paket-Zentrum</strong>&nbsp;auf deiner DiskStation. Suche nach&nbsp;<strong>Container Manager</strong>&nbsp;und klick auf&nbsp;<strong>Installieren</strong>.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440087705f&quot;}" data-wp-interactive="core/image" data-wp-key="69e440087705f" class="wp-block-image aligncenter size-large is-resized wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="771" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/01/BILD-1-n8n-Paket-Zentrum-Container-Manager-installieren-1024x771.png" alt="n8n selber hosten auf Synology NAS: Container Manager über das Paket-Zentrum installieren" class="wp-image-270" style="aspect-ratio:1.3281590470458837;width:780px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/01/BILD-1-n8n-Paket-Zentrum-Container-Manager-installieren-1024x771.png 1024w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-1-n8n-Paket-Zentrum-Container-Manager-installieren-300x226.png 300w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-1-n8n-Paket-Zentrum-Container-Manager-installieren-768x578.png 768w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-1-n8n-Paket-Zentrum-Container-Manager-installieren.png 1149w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 1: Container Manager installieren</figcaption></figure>



<p class="has-text-align-left">Der&nbsp;<strong>Container Manager</strong>&nbsp;ist das, was früher „Docker&#8220; hieß. Ein Werkzeug, um Software in&nbsp;isolierten Umgebungen sogenannten&nbsp;Containern laufen zu lassen.<br>Warum Container? Weil sie&nbsp;sauber getrennt&nbsp;vom Rest des Systems sind. Wenn ein Container abstürzt, crasht nicht die ganze NAS. Wenn du ein Update machst, betrifft es nur den Container. Wenn du n8n deinstallierst, bleiben keine Dateireste zurück.<br>Container sind wie&nbsp;Mini-Computer&nbsp;in deinem Computer: eigenes Dateisystem, eigenes Netzwerk, eigene Prozesse. Aber sie teilen sich die Hardware mit dem Host. Das macht sie schlank und schnell.</p>



<p class="has-text-align-left"><strong>Ulf:</strong>&nbsp;„Also ist das wie eine virtuelle Maschine?&#8220;<br><strong>Tanja:</strong>&nbsp;„Ähnlich, aber viel effizienter. Eine VM braucht ein komplettes Betriebssystem. Ein Container nutzt das Betriebssystem der NAS mit. Deshalb startet ein Container in Sekunden.&#8220;<br><strong>Bernd:</strong>&nbsp;„Und wenn ich den Container lösche, ist alles weg?&#8220;<br><strong>Tanja:</strong>&nbsp;„Der Container ja. Aber die Daten nicht wenn du sie in einem Volume speicherst. Deshalb legen wir jetzt Ordner an.&#8220;</p>



<h4 class="wp-block-heading">Ordnerstruktur in File Station anlegen</h4>



<p>Öffne die&nbsp;<strong>File Station</strong>&nbsp;auf deiner DiskStation. Navigiere zum Ordner&nbsp;<strong><code>docker</code></strong>&nbsp;(wurde automatisch angelegt, als du den Container Manager installiert hast). Erstelle einen&nbsp;<strong>neuen Unterordner</strong>&nbsp;namens&nbsp;<strong><code>n8n</code></strong>.<br>Dein Pfad sollte jetzt so aussehen:&nbsp;<code>/volume1/docker/n8n</code></p>



<p><strong>Warum brauchen wir das?</strong></p>



<p>n8n muss Daten speichern: Workflows, Einstellungen, Logs, hochgeladene Dateien. Ohne einen festen Speicherort gehen diese Daten bei jedem Neustart verloren. Der Ordner&nbsp;<code>/docker/n8n</code>&nbsp;ist dieser Speicherort – ein&nbsp;Volume, das zwischen der NAS und dem Container gemappt wird.<br>Falls du PostgreSQL nutzen willst, leg jetzt schon zwei zusätzliche Unterordner an:</p>



<ul class="wp-block-list">
<li><code>/docker/n8n/app_data</code>&nbsp;– für n8n-Konfiguration und hochgeladene Dateien</li>



<li><code>/docker/n8n/postgres_data</code>&nbsp;– für die Datenbank selbst</li>
</ul>



<p>Deine Struktur sieht dann so aus:</p>



<pre class="wp-block-code"><code>/docker
  └── n8n
      ├── app_data
      └── postgres_data</code></pre>



<p>Falls du SQLite nutzt, reicht der Hauptordner&nbsp;<code>/docker/n8n</code>.</p>



<p>n8n braucht einen Ort, um Daten zu speichern Workflows, Einstellungen, Logs. Das passiert über&nbsp;Volumes, also gemappte Ordner zwischen der DiskStation und dem Container. Ohne diese Ordner gehen bei einem Neustart alle Daten verloren.<br>Im gemeinsamen Ordner&nbsp;<code>docker</code>&nbsp;(der automatisch bei der Installation des Container Managers angelegt wurde) erstellt man einen Unterordner&nbsp;<code>n8n</code>.<br>Falls du dich für&nbsp;PostgreSQL&nbsp;entschieden hast, lege zusätzlich zwei Unterordner an:</p>



<ul class="wp-block-list">
<li><code>/docker/n8n/app_data</code>&nbsp;– für n8n-Konfiguration und verarbeitete Dateien</li>



<li><code>/docker/n8n/postgres_data</code>&nbsp;– für die Datenbank selbst</li>
</ul>



<p><strong>Ulf:</strong>&nbsp;„Warum heißt der Ordner&nbsp;<code>docker</code>? Ich dachte, es heißt jetzt Container Manager?&#8220;<br><strong>Tanja:</strong>&nbsp;„Synology hat umbenannt, aber der Ordner heißt intern immer noch&nbsp;<code>docker</code>. Das ist nur ein Name. Wichtig ist, dass du deine Daten dort ablegst.&#8220;<br><strong>Bernd:</strong>&nbsp;„Kann ich den Ordner auch woanders hinlegen?&#8220;<br><strong>Tanja:</strong>&nbsp;„Kannst du. Aber dann musst du später die Pfade anpassen. Bleib beim Standard, das macht&#8217;s einfacher.&#8220;</p>



<p><strong>Tipp: Dateikomprimierung deaktivieren</strong><br>Falls du auf deinem Volume die&nbsp;Dateikomprimierung&nbsp;aktiviert hast (das ist eine Synology-Funktion, um Speicherplatz zu sparen), solltest du sie für den Ordner&nbsp;<code>postgres_data</code>&nbsp;deaktivieren.<br>Warum? Weil Datenbanken&nbsp;permanent&nbsp;auf ihre Dateien zugreifen lesen, schreiben, ändern. Komprimierung verlangsamt diesen Prozess massiv. PostgreSQL wird träge, Workflows laufen langsamer, manchmal gibt&#8217;s sogar Timeouts.<br>So deaktivierst du die Komprimierung:</p>



<ol class="wp-block-list">
<li>Rechtsklick auf den Ordner&nbsp;<code>postgres_data</code>&nbsp;→&nbsp;<strong>Eigenschaften</strong></li>



<li>Tab&nbsp;<strong>Allgemein</strong>&nbsp;→ Checkbox&nbsp;<strong>Komprimierung aktivieren</strong>&nbsp;deaktivieren</li>



<li>Speichern</li>
</ol>



<p>Für&nbsp;<code>app_data</code>&nbsp;und&nbsp;<code>n8n</code>&nbsp;ist Komprimierung unkritisch. Aber für Datenbanken: niemals.</p>



<h4 class="wp-block-heading">Berechtigungen prüfen</h4>



<p>Rechtsklick auf den Ordner&nbsp;<code>/docker/n8n</code>&nbsp;→&nbsp;<strong>Eigenschaften</strong>&nbsp;→ Tab&nbsp;<strong>Berechtigungen</strong></p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400877a26&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400877a26" class="wp-block-image aligncenter size-full wp-lightbox-container"><img loading="lazy" decoding="async" width="757" height="597" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/01/BILD-2-n8n-Rechtsklick-auf-Ordner-Eigenschaften-Berechtigungen.png" alt="Synology NAS: Rechtsklick auf Ordner – Eigenschaften – Berechtigungen für n8n setzen" class="wp-image-271" srcset="https://www.foundic.org/wp-content/uploads/2026/01/BILD-2-n8n-Rechtsklick-auf-Ordner-Eigenschaften-Berechtigungen.png 757w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-2-n8n-Rechtsklick-auf-Ordner-Eigenschaften-Berechtigungen-300x237.png 300w" sizes="auto, (max-width: 757px) 100vw, 757px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 2: Rechtsklick auf Ordner &#8211; Eigenschaften &#8211; Berechtigungen</figcaption></figure>



<p>Wichtig: Die Gruppe&nbsp;<strong>Everyone</strong>&nbsp;braucht&nbsp;<strong>Lese- und Schreibrechte</strong>.<br>Warum? Weil der Container unter einem anderen Benutzer läuft als du. Wenn die Berechtigungen nicht stimmen, kann n8n nicht auf den Ordner zugreifen und startet entweder gar nicht oder wirft kryptische Fehlermeldungen.<br>Falls die Berechtigung noch nicht gesetzt ist:</p>



<ol class="wp-block-list">
<li>Klick auf&nbsp;<strong>Bearbeiten</strong></li>



<li>Wähle die Gruppe&nbsp;<strong>Everyone</strong></li>



<li>Setze die Haken bei&nbsp;<strong>Lesen</strong>&nbsp;und&nbsp;<strong>Schreiben</strong></li>



<li><strong>Auf Unterordner anwenden</strong>&nbsp;aktivieren</li>



<li>Speichern</li>
</ol>



<p><strong>Bernd:</strong>&nbsp;„Everyone? Das klingt unsicher. Kann dann nicht jeder auf meine Daten zugreifen?&#8220;<br><strong>Tanja:</strong>&nbsp;„Everyone bedeutet hier: alle Benutzer&nbsp;<em>auf dieser NAS</em>. Nicht jeder im Internet. Solange deine NAS nicht öffentlich erreichbar ist, ist das kein Problem.&#8220;<br><strong>Ulf:</strong>&nbsp;„Und wenn ich&#8217;s doch sicherer haben will?&#8220;<br><strong>Tanja:</strong>&nbsp;„Dann erstellst du einen speziellen Benutzer für Docker, gibst nur dem die Rechte und passt die Container-Config an. Aber das ist für den Anfang Overkill.&#8220;</p>



<h4 class="wp-block-heading">Häufige Fehler &amp; Lösungen beim Container-Start</h4>



<p>Einer der häufigsten Fehler beim Start von n8n ist diese Meldung: <code>Error: permission denied open '/home/node/.n8n/config</code></p>



<p>Das bedeutet: Der Container hat keine Schreibrechte auf den Ordner.<br><strong>Lösung 1 </strong>(über die UI):&nbsp;Geh zurück zu&nbsp;<strong>Eigenschaften → Berechtigungen</strong>&nbsp;und prüf, ob&nbsp;<strong>Everyone</strong>&nbsp;wirklich Lese- und Schreibrechte hat. Falls nicht: setzen, speichern, Container neu starten.<br><strong>Lösung 2 </strong>(über SSH, die „Brechstange&#8220;):&nbsp;Falls die UI nicht hilft, öffne eine SSH-Verbindung zur NAS und gib ein:<br>bash</p>



<pre class="wp-block-code"><code>sudo chmod -R 777 /volume1/docker/n8n</code></pre>



<p>Das gibt&nbsp;allen&nbsp;Benutzern&nbsp;volle Rechte&nbsp;auf den Ordner. Das ist nicht besonders elegant, aber es funktioniert. Im produktiven Einsatz solltest du die Rechte später auf den spezifischen Docker-User einschränken aber für den Anfang ist das okay.</p>



<p><strong>Bernd:</strong>&nbsp;„Warum brauche ich SSH? Kann ich das nicht einfach in der Oberfläche machen?&#8220;<br><strong>Tanja:</strong>&nbsp;„In den meisten Fällen ja. Aber manchmal sind die Rechte so verbockt, dass du per Terminal ran musst. Das ist dann der sichere Weg.&#8220;<br><strong>Ulf:</strong>&nbsp;„Okay, Ordner sind da, Rechte sind gesetzt. Was jetzt?&#8220;<br><strong>Tanja:</strong>&nbsp;„Jetzt holen wir uns die Software. Entweder PostgreSQL – oder direkt n8n, wenn du SQLite nimmst.&#8220;</p>



<h3 class="wp-block-heading">3.2 PostgreSQL Image herunterladen <em>(optional, nur wenn du PostgreSQL nutzt)</em></h3>



<p>Wenn du SQLite nutzt, überspring diesen Schritt und geh direkt zu Schritt 3.5. Wenn du lieber Docker Compose nutzen willst, spring direkt zu Schritt 3.4.<br>Für PostgreSQL brauchen wir zuerst das&nbsp;Image&nbsp;eine Art Vorlage für den Container. Synology lädt diese Images aus einer öffentlichen Registrierung herunter (dem „Docker Hub&#8220;).<br>Öffne den&nbsp;<strong>Container Manager</strong>&nbsp;→ Tab&nbsp;<strong>Registrierung</strong><br>In der Suchleiste: Tipp&nbsp;<code>postgres</code>&nbsp;ein.<br>Es erscheinen mehrere Ergebnisse. Du willst das&nbsp;offizielle&nbsp;Image, erkennbar am grünen „Docker Official Image&#8220;-Badge.<br>Klick darauf →&nbsp;<strong>Download</strong><br>Jetzt musst du einen&nbsp;<strong>Tag</strong>&nbsp;auswählen. Ein Tag ist eine Versionsnummer.<br>Wähl&nbsp;<strong><code>16</code></strong>. Das ist die aktuelle stabile Version (Stand Januar 2025) und wird längerfristig unterstützt.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e44008782bc&quot;}" data-wp-interactive="core/image" data-wp-key="69e44008782bc" class="wp-block-image aligncenter size-large is-resized wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="647" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/01/BILD-3-Container-Manager-Registrierung-nach-22postgres22-suchen-Image-auswaehlen-1024x647.png" alt="Synology Container Manager: Registrierung nach postgres suchen und Image 16 auswählen" class="wp-image-272" style="aspect-ratio:1.5827089052105745;width:808px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/01/BILD-3-Container-Manager-Registrierung-nach-22postgres22-suchen-Image-auswaehlen-1024x647.png 1024w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-3-Container-Manager-Registrierung-nach-22postgres22-suchen-Image-auswaehlen-300x189.png 300w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-3-Container-Manager-Registrierung-nach-22postgres22-suchen-Image-auswaehlen-768x485.png 768w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-3-Container-Manager-Registrierung-nach-22postgres22-suchen-Image-auswaehlen.png 1205w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 3: Container Manager &#8211; Registrierung nach &#8222;postgres&#8220; suchen &#8211; Image 16 auswählen</figcaption></figure>



<p>Der Download läuft ein paar Minuten. Du siehst den Fortschritt im Tab&nbsp;<strong>Image</strong>. Sobald der Download fertig ist, kannst du weitermachen.</p>



<p><strong>Ulf:</strong>&nbsp;„Warum nicht einfach&nbsp;<code>latest</code>&nbsp;nehmen? Dann hab ich immer die neueste Version.&#8220;<br><strong>Tanja:</strong>&nbsp;„Weil&nbsp;<code>latest</code>&nbsp;gefährlich ist. Wenn PostgreSQL ein großes Update macht zum Beispiel von Version 16 auf 17, kann es sein, dass deine Datenbank nicht mehr kompatibel ist. Plötzlich startet nichts mehr, und du weißt nicht warum. Mit einer festen Version bist du sicher.&#8220;<br><strong>Bernd:</strong>&nbsp;„Aber dann muss ich doch später manuell updaten?&#8220;<br><strong>Tanja:</strong>&nbsp;„Ja. Aber lieber kontrolliert updaten als ungewollt kaputt updaten.&#8220;</p>



<h3 class="wp-block-heading">3.3 PostgreSQL Datenbank einrichten <em>(optional)</em></h3>



<p>Jetzt konfigurieren wir den PostgreSQL-Container. Das ist der Teil, den viele als kompliziert empfinden aber wenn du weißt, was jede Einstellung bedeutet, ist es easy.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Einstellung</th><th>Wert / Empfehlung</th></tr></thead><tbody><tr><td>Container-Name</td><td><code>n8n-postgres</code></td></tr><tr><td>Ressourcenbeschränkung</td><td>Nicht aktivieren</td></tr><tr><td>Automatischen Neustart</td><td>Aktivieren</td></tr><tr><td>Web-Portal via Web Station</td><td>Nicht aktivieren</td></tr><tr><td>Port-Einstellungen</td><td>Lokaler Port: <code>5433</code>, Container-Port:&nbsp;<code>5432</code>, Typ:<code>TCP</code></td></tr><tr><td>Volume-Einstellungen</td><td>Ordner:&nbsp;<code>/docker/n8n/postgres_data</code>&nbsp;auswählen<br>Feld Mount-Pfade:&nbsp;<code>/var/lib/postgresql/data</code></td></tr><tr><td>Umgebungsvariablen</td><td>&#8211; Variable: <code>POSTGRES_USER</code> und Wert: <code>n8n_admin</code><br>&#8211; Variable: <code>POSTGRES_PASSWORD</code> und Wert: <em>zufälliges Passwort</em><br>&#8211; Variable: <code>POSTGRES_DB</code>&nbsp;und Wert: <code>n8n_db</code></td></tr><tr><td>Netwerk</td><td><code>bridge</code>&nbsp;(Standard)</td></tr><tr><td>Geh in den&nbsp;<strong>Container Manager</strong>&nbsp;→ Tab&nbsp;<strong>Image</strong>&nbsp;Such das Image&nbsp;<strong><code>postgres:16</code></strong>&nbsp;→ Klick drauf →&nbsp;<strong>Ausführen</strong></td><td></td></tr><tr><td>Es öffnet sich ein Assistent. Wir gehen Schritt für Schritt durch</td><td></td></tr></tbody></table></figure>



<h4 class="wp-block-heading">Schritt 1: Allgemeine Einstellungen</h4>



<p><strong>Container-Name:</strong> <code>n8n-postgres</code><br>Das ist einfach der Name, unter dem der Container später läuft. Du kannst ihn frei wählen, aber nimm was Sinnvolles. Wenn du irgendwann mehrere Datenbanken hast, willst du nicht raten müssen, welche zu n8n gehört.<br><strong>Ressourcenbeschränkung:</strong> Nicht aktivieren (vorerst)<br>Du kannst Container auf eine bestimmte Menge RAM oder CPU beschränken. Das macht Sinn, wenn du viele Container laufen hast und die NAS nicht überlasten willst. Aber für den Anfang: lass es aus. Falls PostgreSQL später zu viel frisst, stellst du Mittel ein und setzt das RAM-Limit auf 2048 MB oder 4096 MB.<br><strong>Automatischen Neustart:</strong> Aktivieren<br>Das ist wichtig. Wenn die NAS neu startet wegen eines Updates, eines Stromausfalls, was auch immer – soll PostgreSQL automatisch wieder hochfahren. Sonst steht n8n plötzlich ohne Datenbank da und du wunderst dich, warum nichts mehr geht.<br><strong>Web-Portal via Web Station einrichten:</strong> Nicht aktivieren<br>Das ist eine Synology-Komfortfunktion, um Container über eine schicke Weboberfläche erreichbar zu machen. Brauchen wir hier nicht. PostgreSQL hat eh keine Web-UI.<br>Klick auf <strong>Weiter</strong>.</p>



<h4 class="wp-block-heading">Schritt 2: Port-Einstellungen</h4>



<p>PostgreSQL läuft standardmäßig auf Port <strong>5432</strong>. Aber: Wenn du mehrere Datenbanken auf der NAS hast, kann es sein, dass dieser Port schon belegt ist.<br>Deshalb mappen wir:</p>



<ul class="wp-block-list">
<li><strong>Lokaler Port:</strong> <code>5433</code></li>



<li><strong>Container-Port:</strong> <code>5432</code></li>



<li><strong>Typ:</strong> <code>TCP</code></li>
</ul>



<p>Das bedeutet: Intern im Container läuft PostgreSQL auf 5432 (wie üblich). Aber von außen also von der NAS oder von n8n aus greifst du über 5433 zu.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400878adb&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400878adb" class="wp-block-image aligncenter size-full wp-lightbox-container"><img loading="lazy" decoding="async" width="612" height="475" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/01/BILD-4-Einstellungen-Port-Volumen.png" alt="PostgreSQL Container Einstellungen: Lokaler Port 5433, Container-Port 5432 konfigurieren" class="wp-image-274" srcset="https://www.foundic.org/wp-content/uploads/2026/01/BILD-4-Einstellungen-Port-Volumen.png 612w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-4-Einstellungen-Port-Volumen-300x233.png 300w" sizes="auto, (max-width: 612px) 100vw, 612px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 4: Einstellungen &#8211; Lokaler Port 5433, Container-Port 5432</figcaption></figure>



<p><strong>Wichtig:</strong> Prüf, ob der Port in der Firewall freigegeben ist. Geh dazu in die <strong>Systemsteuerung → Sicherheit → Firewall → Regeln bearbeiten</strong>. Falls eine Firewall aktiv ist, füg eine Regel hinzu, die Port 5433 für lokale Verbindungen zulässt.<br>Klick auf <strong>Weiter</strong>.</p>



<p><strong>Ulf:</strong> „Warum ist der Port überhaupt wichtig? Kann ich da nicht einfach irgendwas eintragen?&#8220;<br><strong>Tanja:</strong> „Ein Port ist wie eine Tür in einem Gebäude. Jede Anwendung braucht ihre eigene Tür, damit die Daten wissen, wo sie hin müssen. Wenn zwei Anwendungen dieselbe Tür nutzen wollen, gibt&#8217;s Ärger.&#8220;<br><strong>Bernd:</strong> „Und wenn ich nicht weiß, ob ein Port frei ist?&#8220;<br><strong>Tanja:</strong> „Dann probier&#8217;s einfach aus. Wenn der Container nicht startet und eine Fehlermeldung kommt wie &#8218;Port already in use&#8216;, nimm einen anderen.&#8220;</p>



<h4 class="wp-block-heading">Schritt 3: Volume-Einstellungen</h4>



<p>Hier passiert die Magie: Du verbindest den Container mit einem Ordner auf der NAS.<br>Klick auf <strong>Ordner hinzufügen</strong> → Wähl <code>/docker/n8n/postgres_data</code><br>Im Feld <strong>Mount-Pfad</strong> trägst du ein: <code>/var/lib/postgresql/data</code><br>Das bedeutet: Alles, was PostgreSQL im Container unter <code>/var/lib/postgresql/data</code> speichert (also die gesamte Datenbank), landet tatsächlich auf der NAS unter <code>/docker/n8n/postgres_data</code>.<br>Warum ist das wichtig? Weil Container flüchtig sind. Wenn du den Container löschst, sind alle Daten darin weg. Aber wenn die Daten auf der NAS liegen, bleiben sie erhalten. Du kannst den Container updaten, neu starten, löschen – die Datenbank bleibt.<br>Klick auf <strong>Weiter</strong>.</p>



<p><strong>Bernd:</strong> „Kann ich auch mehrere Volumes haben?&#8220;<br><strong>Tanja:</strong> „Klar. Aber PostgreSQL braucht nur eins. Für n8n brauchen wir später ein zweites.&#8220;</p>



<h4 class="wp-block-heading">Schritt 4: Umgebungsvariablen</h4>



<p>Umgebungsvariablen sind Konfigurationseinstellungen, die dem Container mitteilen, wie er sich verhalten soll. Für PostgreSQL sind drei wichtig:<br>Klick auf <strong>+ Hinzufügen</strong> und trag folgendes ein:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Variable</th><th>Wert</th><th>Erklärung</th></tr></thead><tbody><tr><td>POSTGRES_USER</td><td><code>n8n_admin</code></td><td>Das ist der Benutzername für die Datenbank. Du brauchst ihn später, um n8n mit PostgreSQL zu verbinden.</td></tr><tr><td>POSTGRES_PASSWORD</td><td><em>sicheres Passwort</em><br>&lt;POSTGRES_PASSWORD&gt;</td><td>Das Passwort für den Benutzer. Nimm ein zufälliges Passwort, mindestens 20 Zeichen, Buchstaben, Zahlen, Sonderzeichen. Speichere es in einem Passwort-Manager.</td></tr><tr><td>POSTGRES_DB</td><td><code>n8n_db</code></td><td>Das ist der Name der Datenbank selbst. PostgreSQL legt sie beim Start automatisch an.</td></tr></tbody></table></figure>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440087927d&quot;}" data-wp-interactive="core/image" data-wp-key="69e440087927d" class="wp-block-image aligncenter size-large is-resized wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="683" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-5-Einstellungen-Umgebungsvariablen-1-1024x683.png" alt="PostgreSQL Container: Umgebungsvariablen für n8n Datenbankverbindung konfigurieren" class="wp-image-760" style="aspect-ratio:1.4992854967554525;width:642px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-5-Einstellungen-Umgebungsvariablen-1-1024x683.png 1024w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-5-Einstellungen-Umgebungsvariablen-1-300x200.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-5-Einstellungen-Umgebungsvariablen-1-768x512.png 768w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-5-Einstellungen-Umgebungsvariablen-1.png 1536w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 5: Einstellungen &#8211; Umgebungsvariablen</figcaption></figure>



<p><strong>Wichtig:</strong> Schreib das Passwort irgendwo auf. Du brauchst es gleich, wenn wir n8n konfigurieren.<br>Klick auf <strong>Weiter</strong>.</p>



<p><strong>Ulf:</strong> „Kann ich das Passwort auch einfach lassen? Also leer?&#8220;<br><strong>Tanja:</strong> „Nein. PostgreSQL startet ohne Passwort gar nicht erst. Und selbst wenn – das wäre ein riesiges Sicherheitsrisiko.&#8220;<br><strong>Bernd:</strong> „Und wenn ich das Passwort vergesse?&#8220;<br><strong>Tanja:</strong> „Dann kannst du dich nicht mehr in die Datenbank einloggen. Musst alles neu aufsetzen. Also: Passwort-Manager.&#8220;</p>



<h4 class="wp-block-heading">Schritt 5: Netzwerk</h4>



<p>Hier bleibt alles auf <strong>Standard</strong>.<br>Das Netzwerk heißt <strong><code>bridge</code></strong> – das ist das Default-Netzwerk, in dem alle Container miteinander kommunizieren können.<br>Klick auf <strong>Weiter</strong>.</p>



<h4 class="wp-block-heading">Schritt 6: Zusammenfassung</h4>



<p>Synology zeigt dir jetzt eine Übersicht aller Einstellungen. Prüf nochmal:</p>



<ul class="wp-block-list">
<li>Container-Name: <code>n8n-postgres</code></li>



<li>Automatischer Neustart: aktiviert</li>



<li>Port: 5433 → 5432</li>



<li>Volume: <code>/docker/n8n/postgres_data</code> → <code>/var/lib/postgresql/data</code></li>



<li>Umgebungsvariablen: User, Passwort, DB-Name gesetzt<br>Alles korrekt? Klick auf <strong>Fertig</strong>.<br>Der Container startet. Nach ein paar Sekunden sollte er im Tab <strong>Container</strong> als <strong>läuft</strong> angezeigt werden.</li>
</ul>



<p><strong>Ulf:</strong> „Woher weiß ich, ob PostgreSQL wirklich funktioniert?&#8220;<br><strong>Tanja:</strong> „Du kannst die Logs checken. Geh in den Container Manager, klick auf den Container <code>n8n-postgres</code>, dann auf <strong>Details</strong> → <strong>Log</strong>. Da solltest du eine Zeile sehen wie: <code>database system is ready to accept connections</code>. Dann läuft&#8217;s.&#8220;<br><strong>Bernd:</strong> „Und wenn da ein Fehler steht?&#8220;<br><strong>Tanja:</strong> „Dann lies die Fehlermeldung. Meist ist es ein Problem mit den Berechtigungen oder den Umgebungsvariablen. Geh die Schritte nochmal durch.&#8220;</p>



<h3 class="wp-block-heading">3.4 Projekt-Variante mit Docker Compose&nbsp;<em>(Alternative)</em></h3>



<p>Docker Compose ist eine Methode, um mehrere Container mit einer einzigen Konfigurationsdatei zu starten. Statt jeden Container einzeln zu konfigurieren, schreibst du alles in eine Datei und fertig.<br><strong>Warum solltest du Docker Compose nutzen?</strong></p>



<ul class="wp-block-list">
<li><strong>Wiederholbar:</strong> Du kannst die Konfiguration speichern, sichern, auf andere Systeme übertragen.</li>



<li><strong>Einfache Wartung:</strong> Alle Dienste (n8n, PostgreSQL) werden gemeinsam gestartet und gestoppt.</li>



<li><strong>Skalierbar:</strong> Wenn du später noch Redis, einen Reverse-Proxy oder andere Dienste hinzufügen willst, erweiterst du einfach die Datei.<br><strong>Für wen ist Docker Compose?</strong><br>Für alle, die gerne <strong>Code</strong> statt <strong>UI</strong> nutzen. Wenn du lieber Einstellungen in einer Textdatei pflegst als durch Menüs zu klicken, ist das dein Weg.</li>
</ul>



<h4 class="wp-block-heading">Schritt 1: Projekt erstellen</h4>



<p>Öffne den <strong>Container Manager</strong> → Tab <strong>Projekt</strong> → <strong>Erstellen</strong><br><strong>Projektname:</strong> <code>n8n-stack</code> (oder wie auch immer du es nennen willst)<br><strong>Pfad:</strong> <code>/volume1/docker/n8n</code><br><strong>Quelle:</strong> „docker-compose.yml erstellen&#8220;<br>Jetzt öffnet sich ein Texteditor. Lösch alles, was da steht, und füg folgenden Code ein:</p>



<pre class="wp-block-code"><code>version: '3.8'

services:
  db:
    image: postgres:16
    container_name: n8n-postgres
    restart: unless-stopped
    environment:
      - POSTGRES_USER=n8n_admin
      - POSTGRES_PASSWORD=Dein_Postgress_Passwort
      - POSTGRES_DB=n8n_db
    volumes:
      - /volume1/docker/n8n/postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: &#91;"CMD-SHELL", "pg_isready -U n8n_admin -d n8n_db"]
      interval: 5s
      timeout: 5s
      retries: 5
    networks:
      - n8n-network

  n8n:
    image: n8nio/n8n:latest
    container_name: n8n-app
    restart: unless-stopped
    ports:
      - "5678:5678"
    environment:
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=db
      - DB_POSTGRESDB_PORT=5432
      - DB_POSTGRESDB_DATABASE=n8n_db
      - DB_POSTGRESDB_USER=n8n_admin
      - DB_POSTGRESDB_PASSWORD=Dein_Postgress_Passwort
      - N8N_ENCRYPTION_KEY=Dein_Encryption_Key
      - N8N_SECURE_COOKIE=false
      - WEBHOOK_URL=https://n8n.deine-domain.xyz/
    volumes:
      - /volume1/docker/n8n/app_data:/home/node/.n8n
    depends_on:
      db:
        condition: service_healthy
    networks:
      - n8n-network

networks:
  n8n-network:
    driver: bridge</code></pre>



<p><strong>Was passiert hier?</strong></p>



<ul class="wp-block-list">
<li>Wir definieren <strong>zwei Dienste</strong>: <code>db</code> (PostgreSQL) und <code>n8n</code> (n8n selbst).</li>



<li>Beide laufen im selben Netzwerk (<code>n8n-network</code>), können also miteinander kommunizieren.</li>



<li>n8n wartet, bis PostgreSQL bereit ist (<code>depends_on</code> mit <code>service_healthy</code>).</li>



<li>Alle Einstellungen, die wir vorher einzeln geklickt haben, stehen jetzt in dieser Datei.<br><strong>Was musst du anpassen?</strong></li>
</ul>



<ol class="wp-block-list">
<li><strong>Passwort:</strong> Ersetze <code>Dein_Postgress_Passwort</code> durch dein eigenes sicheres Passwort (mindestens 20 Zeichen, zufällig generiert).</li>



<li><strong>Encryption Key:</strong> Ersetze <code>Dein_Encryption_Key</code> durch einen zufälliges Passwort Deiner Wahl. &nbsp;Ohne <code>N8N_ENCRYPTION_KEY</code> riskierst du bei Neuinstallation oder Umzug unlesbare Secrets.</li>



<li><strong>Webhook URL:</strong> Wenn du später Cloudflare oder eine eigene Domain nutzen willst, trag die hier ein. Vorerst kannst du das auch weglassen oder auf <code>http://DEINE-NAS-IP:5678/</code> setzen.<br>Klick auf <strong>Weiter</strong>, dann auf <strong>Fertig</strong>.<br>Das System lädt jetzt beide Images herunter (falls noch nicht geschehen) und startet die Container. Das kann ein paar Minuten dauern.</li>
</ol>



<p><strong>Ulf:</strong> „Okay, das sieht kompliziert aus. Muss ich das alles verstehen?&#8220;<br><strong>Tanja:</strong> „Nicht jedes Detail. Aber du solltest grob wissen, was passiert: Zwei Container werden gestartet, beide bekommen ihre Einstellungen, beide können miteinander reden. Fertig.&#8220;<br><strong>Bernd:</strong> „Und wenn ich was ändern will?&#8220;<br><strong>Tanja:</strong> „Dann gehst du zurück zum Projekt, klickst auf <strong>Bearbeiten</strong>, änderst die Datei und startest neu. Alles zentral.&#8220;</p>



<h4 class="wp-block-heading">Schritt 2: Prüfen, ob alles läuft</h4>



<p>Geh in den <strong>Container Manager</strong> → Tab <strong>Container</strong><br>Du solltest jetzt zwei Container sehen:</p>



<ul class="wp-block-list">
<li><code>n8n-postgres</code> – Status: <strong>läuft</strong></li>



<li><code>n8n-app</code> – Status: <strong>läuft</strong><br>Zusätzlich sollte mach ein paar Sekunden auf Cloudflare der Tunnel als&nbsp;<strong>&#8222;Healthy&#8220;</strong> angezeigt werden. Jetzt ist n8n über die Domain erreichbar:&nbsp;<code>https://n8n.deine-domain.xyz</code><br>Falls einer nicht läuft, klick drauf und schau ins <strong>Log</strong>. Meist ist es ein Tippfehler in der YAML-Datei oder ein Problem mit den Berechtigungen.<br>Wenn beide laufen, kannst du direkt zu <strong>Schritt 3.7</strong> springen.</li>
</ul>



<p><strong>Tanja:</strong> „Docker Compose ist mein bevorzugter Weg. Einmal richtig aufgesetzt, läuft&#8217;s. Und wenn ich das Setup auf eine andere NAS übertragen will, kopiere ich einfach die Datei.&#8220;<br><strong>Ulf:</strong> „Aber ich muss doch auch die Ordner mitnehmen, oder?&#8220;<br><strong>Tanja:</strong> „Klar. Ordner kopieren, docker-compose.yml anpassen, starten. Aber das ist immer noch schneller als alles neu zu klicken.&#8220;</p>



<h3 class="wp-block-heading">3.5 n8n Image herunterladen</h3>



<p>Wenn du Docker Compose genutzt hast, überspring diesen Schritt. Jetzt holen wir uns n8n selbst. Auch hier brauchen wir zuerst das Image.<br>Öffne den <strong>Container Manager</strong> → Tab <strong>Registrierung</strong><br>In der Suchleiste: Tipp <strong><code>n8nio/n8n</code></strong> ein.<br>Das offizielle n8n-Image erscheint. Klick darauf → <strong>Download</strong><br>Wähl den Tag <strong><code>latest</code></strong>.</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440087a269&quot;}" data-wp-interactive="core/image" data-wp-key="69e440087a269" class="wp-block-image aligncenter size-large is-resized wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="645" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/01/BILD-6-Container-Manager-Registrierung-nach-n8nion8n-suchen-1024x645.png" alt="Synology Container Manager: Registrierung nach n8nio/n8n suchen und Image auswählen" class="wp-image-276" style="aspect-ratio:1.5876165905933717;width:818px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/01/BILD-6-Container-Manager-Registrierung-nach-n8nion8n-suchen-1024x645.png 1024w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-6-Container-Manager-Registrierung-nach-n8nion8n-suchen-300x189.png 300w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-6-Container-Manager-Registrierung-nach-n8nion8n-suchen-768x484.png 768w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-6-Container-Manager-Registrierung-nach-n8nion8n-suchen.png 1209w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 6: Container Manager &#8211; Registrierung &#8211; nach n8nio/n8n suchen</figcaption></figure>



<p>Bei n8n ist <code>latest</code> okay, weil die Entwickler sehr sauber versionieren und Updates meist problemlos laufen. Wenn du es sicherer haben willst, wähl eine feste Version (z. B. <code>1.70.0</code> oder was auch immer aktuell ist).<br>Der Download läuft ein paar Minuten. Sobald er fertig ist, geht&#8217;s weiter.</p>



<p><strong>Bernd:</strong> „Warum heißt das Image <code>n8nio/n8n</code>? Das klingt komisch.&#8220;<br><strong>Tanja:</strong> „Das ist die Namenskonvention auf Docker Hub. <code>n8nio</code> ist der Herausgeber, <code>n8n</code> ist das Produkt. So wie <code>postgres</code> für PostgreSQL.&#8220;</p>



<h3 class="wp-block-heading">3.6 n8n Container konfigurieren</h3>



<p>Jetzt kommt der längste Schritt aber auch der wichtigste. Hier stellst du ein, wie n8n laufen soll.<br>Die wichtigsten Einstellungen:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Einstellung</th><th>Wert / Empfehlung</th></tr></thead><tbody><tr><td>Container-Name</td><td><code>n8n</code></td></tr><tr><td>Ressourcenbeschränkung</td><td>Nicht aktivieren</td></tr><tr><td>Automatischen Neustart</td><td>Aktivieren</td></tr><tr><td>Web-Portal via Web Station</td><td>Nicht aktivieren</td></tr><tr><td>Port-Einstellungen</td><td>Lokaler Port: <code>5678</code>, Container-Port:&nbsp;<code>5678</code>, Typ: <code>TCP</code></td></tr><tr><td>Volume-Einstellungen</td><td>Für <strong>SQLite</strong>:<br>Ordner:&nbsp;<code>/docker/n8n</code>&nbsp;auswählen<br>Feld Mount-Pfade:&nbsp;<code>/home/node/.n8n</code><br>Stattdessen für <strong>PostgreSQL</strong>:<br>Ordner:&nbsp;<code>/docker/n8n/db_data</code>&nbsp;auswählen<br>Feld Mount-Pfade:&nbsp;<code>/home/node/.n8n</code></td></tr><tr><td>Umgebungsvariablen<br>(für <strong>SQLite</strong> und <strong>PostgreSQL</strong>)</td><td>&#8211; Variable: <code>TZ</code> und Wert: <code>Europe/Berlin</code><br>&#8211; Variable: <code>GENERIC_TIMEZONE</code>und Wert: <code>Europe/Berlin</code><br>&#8211; Variable:<code>N8N_ENCRYPTION_KEY</code>&nbsp;und Wert: <em>zufälliges Passwort</em><br>&#8211; Variable:<code>WEBHOOK_URL</code>&nbsp;und Wert: <code>https://n8n.deine-domain.de/</code></td></tr><tr><td><em>(Übergangslösung)</em></td><td><em>&#8211; Variable: <code>N8N_SECURE_COOKIE</code> und Wert: <code>false</code></em></td></tr><tr><td>Umgebungsvariablen (zusätzlich für <strong>PostgreSQL</strong>)</td><td>&#8211; Variable: <code>DB_TYPE</code> und Wert: <code>postgresdb</code><br>&#8211; Variable: <code>DB_POSTGRESDB_HOST</code> und Wert: <em>IP deiner NAS</em>&nbsp;(z. B.&nbsp;<code>192.168.178.50</code>)<br>&#8211; Variable: <code>DB_POSTGRESDB_PORT</code> und Wert: <code>5433</code><br>&#8211; Variable: <code>DB_POSTGRESDB_DATABASE</code> und Wert: <code>n8n_db</code><br>&#8211; Variable: <code>DB_POSTGRESDB_USER</code> und Wert: <code>n8n_admin</code><br>&#8211; Variable: <code>DB_POSTGRESDB_PASSWORD</code> und Wert: <em>Passwort</em></td></tr><tr><td>Netwerk</td><td><code>bridge</code>&nbsp;(Standard)</td></tr></tbody></table></figure>



<p>Geh in den <strong>Container Manager</strong> → Tab <strong>Image</strong> Such das Image <strong><code>n8nio/n8n:latest</code></strong> → Klick drauf → <strong>Ausführen</strong><br>Es öffnet sich wieder der Assistent. Wir gehen Schritt für Schritt durch.</p>



<h4 class="wp-block-heading">Schritt 1: Allgemeine Einstellungen</h4>



<p><strong>Container-Name:</strong> <code>n8n-app</code><br><strong>Ressourcenbeschränkung:</strong> Nicht aktivieren (vorerst)<br>n8n ist normalerweise sparsam. Aber wenn du viele Workflows parallel laufen lässt oder große Dateien verarbeitest, kann es RAM ziehen. Falls nötig, stell später <strong>Mittel</strong> ein und begrenze auf 2–4 GB.<br><strong>Automatischen Neustart:</strong> Aktivieren<br>Wie bei PostgreSQL: Wenn die NAS neu startet, soll n8n automatisch wieder hochfahren.<br><strong>Web-Portal via Web Station einrichten:</strong> Nicht aktivieren<br>Brauchen wir nicht. n8n hat eine eigene Web-UI.<br>Klick auf <strong>Weiter</strong>.</p>



<h4 class="wp-block-heading">Schritt 2: Port-Einstellungen</h4>



<p>n8n läuft standardmäßig auf Port <strong>5678</strong>. Das ist auch der Port, über den du später im Browser zugreifst.<br>Trag ein:</p>



<ul class="wp-block-list">
<li><strong>Lokaler Port:</strong> <code>5678</code></li>



<li><strong>Container-Port:</strong> <code>5678</code></li>



<li><strong>Typ:</strong> <code>TCP</code></li>
</ul>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440087ac0b&quot;}" data-wp-interactive="core/image" data-wp-key="69e440087ac0b" class="wp-block-image aligncenter size-full is-resized wp-lightbox-container"><img loading="lazy" decoding="async" width="751" height="587" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/01/BILD-7-Einstellungen-Port-Volumen.png" alt="n8n Container Einstellungen: Port und Volumen für Synology NAS konfigurieren" class="wp-image-277" style="width:689px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/01/BILD-7-Einstellungen-Port-Volumen.png 751w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-7-Einstellungen-Port-Volumen-300x234.png 300w" sizes="auto, (max-width: 751px) 100vw, 751px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 7: Einstellungen &#8211; Port &#8211; Volumen</figcaption></figure>



<p><strong>Wichtig:</strong> Prüf die Firewall. Geh in die <strong>Systemsteuerung → Sicherheit → Firewall → Regeln bearbeiten</strong> und stell sicher, dass Port 5678 für lokale Verbindungen freigegeben ist.<br>Klick auf <strong>Weiter</strong>.</p>



<h4 class="wp-block-heading">Schritt 3: Volume-Einstellungen</h4>



<p>Hier unterscheiden wir uns jetzt je nachdem, ob du <strong>SQLite</strong> oder <strong>PostgreSQL</strong> nutzt.<br><strong>Für SQLite:</strong></p>



<ul class="wp-block-list">
<li>Klick auf <strong>Ordner hinzufügen</strong> → Wähl <code>/docker/n8n</code></li>



<li>Im Feld <strong>Mount-Pfad</strong>: <code>/home/node/.n8n</code><br><strong>Für PostgreSQL:</strong></li>



<li>Klick auf <strong>Ordner hinzufügen</strong> → Wähl <code>/docker/n8n/app_data</code></li>



<li>Im Feld <strong>Mount-Pfad</strong>: <code>/home/node/.n8n</code><br>Das bedeutet: Alle Daten, die n8n im Container unter <code>/home/node/.n8n</code> speichert (Workflows, Einstellungen, Logs), landen auf der NAS unter <code>/docker/n8n</code> bzw. <code>/docker/n8n/app_data</code>.<br>Klick auf <strong>Weiter</strong>.</li>
</ul>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Variable</th><th>Wert</th><th>Erklärung</th></tr></thead><tbody><tr><td>TZ</td><td><code>Europe/Berlin</code></td><td>Die Zeitzone. Wichtig für zeitgesteuerte Workflows. Ohne das läuft alles in UTC.</td></tr><tr><td>GENERIC_TIMEZONE</td><td><code>Europe/Berlin</code></td><td>Gleiche Zeitzone, nochmal für n8n-interne Prozesse.</td></tr><tr><td>N8N_ENCRYPTION_KEY</td><td><em>zufälliges Passwort</em></td><td>Ein Schlüssel, mit dem n8n sensible Daten verschlüsselt (z. B. API-Keys). Ohne diesen Key riskierst du bei einer Neuinstallation, dass gespeicherte Credentials unlesbar werden. Mindestens 20 Zeichen, Buchstaben und Zahlen.</td></tr><tr><td>WEBHOOK_URL</td><td><code>https://n8n.deine-domain.de/</code></td><td>Die URL, unter der n8n von außen erreichbar ist. <strong>Wichtig:</strong> Der Schrägstrich am Ende ist zwingend, sonst funktionieren Webhooks nicht. Falls du noch keine Domain hast, trag vorerst <code>http://DEINE-NAS-IP:5678/</code> ein.</td></tr><tr><td>N8N_SECURE_COOKIE</td><td><code>false</code></td><td><strong>Übergangslösung.</strong> Normalerweise sollte das <code>true</code> sein (für HTTPS), aber solange du noch kein SSL-Zertifikat hast, muss es auf <code>false</code> stehen. Sonst kannst du dich nicht einloggen. Sobald du in Schritt 8 Cloudflare eingerichtet hast, änderst du das auf <code>true</code>.</td></tr></tbody></table></figure>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440087b3fc&quot;}" data-wp-interactive="core/image" data-wp-key="69e440087b3fc" class="wp-block-image aligncenter size-full is-resized wp-lightbox-container"><img loading="lazy" decoding="async" width="779" height="596" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-8-Einstellungen-Umgebungsvariablen.png" alt="n8n Container: Umgebungsvariablen auf Synology NAS setzen" class="wp-image-498" style="width:709px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-8-Einstellungen-Umgebungsvariablen.png 779w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-8-Einstellungen-Umgebungsvariablen-300x230.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-8-Einstellungen-Umgebungsvariablen-768x588.png 768w" sizes="auto, (max-width: 779px) 100vw, 779px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 8: Einstellungen &#8211; Umgebungsvariablen</figcaption></figure>



<p><strong>Zusätzlich für PostgreSQL:</strong><br>Falls du PostgreSQL nutzt, kommen jetzt noch ein paar Variablen dazu:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Variable</th><th>Wert</th><th>Erklärung</th></tr></thead><tbody><tr><td>DB_TYPE</td><td><code>postgresdb</code></td><td>Sagt n8n, dass es PostgreSQL nutzen soll (statt SQLite).</td></tr><tr><td>DB_POSTGRESDB_HOST</td><td><em>IP deiner NAS</em></td><td>Die Adresse, unter der PostgreSQL läuft. Zum Beispiel <code>192.168.178.50</code>. Nicht <code>localhost</code>, das funktioniert in Containern nicht.</td></tr><tr><td>DB_POSTGRESDB_PORT</td><td><code>5433</code></td><td>Der Port, den wir vorhin bei PostgreSQL eingestellt haben.</td></tr><tr><td>DB_POSTGRESDB_DATABASE</td><td><code>n8n_db</code></td><td>Der Name der Datenbank.</td></tr><tr><td>DB_POSTGRESDB_USER</td><td><code>n8n_admin</code></td><td>Der Benutzername.</td></tr><tr><td>DB_POSTGRESDB_PASSWORD</td><td><em>Das Passwort aus Schritt 3</em></td><td>Das Passwort, das du bei PostgreSQL gesetzt hast.</td></tr><tr><td>Klick auf <strong>Weiter</strong>.</td><td></td><td></td></tr></tbody></table></figure>



<p><strong>Ulf:</strong> „Warum muss ich die IP der NAS eintragen? Ich dachte, die Container laufen doch auf derselben Maschine?&#8220;<br><strong>Tanja:</strong> „Tun sie. Aber jeder Container hat sein eigenes Netzwerk. Wenn n8n <code>localhost</code> anspricht, meint es <em>seinen eigenen</em> Container nicht die NAS. Deshalb musst du die NAS-IP angeben.&#8220;<br><strong>Bernd:</strong> „Und wenn ich die IP nicht weiß?&#8220;<br><strong>Tanja:</strong> „Dann guck in die <strong>Systemsteuerung → Netzwerk → Netzwerkschnittstelle</strong>. Da steht&#8217;s.&#8220;</p>



<h4 class="wp-block-heading">Schritt 5: Netzwerk</h4>



<p>Auch hier bleibt alles auf <strong>Standard</strong>: <code>bridge</code>.<br>Klick auf <strong>Weiter</strong>.</p>



<h4 class="wp-block-heading">Schritt 6: Zusammenfassung</h4>



<p>Synology zeigt dir nochmal alle Einstellungen. Prüf:</p>



<ul class="wp-block-list">
<li>Container-Name: <code>n8n-app</code></li>



<li>Automatischer Neustart: aktiviert</li>



<li>Port: 5678 → 5678</li>



<li>Volume: richtig gemappt</li>



<li>Umgebungsvariablen: alles gesetzt<br>Alles korrekt? Klick auf <strong>Fertig</strong>.<br>Der Container startet.</li>
</ul>



<p><strong>Tanja:</strong> „Und jetzt die spannende Frage: Läuft&#8217;s?&#8220;<br><strong>Ulf:</strong> „Woher weiß ich das?&#8220;<br><strong>Tanja:</strong> „Öffne deinen Browser und gib ein: <code>http://DEINE-NAS-IP:5678</code>&#8222;</p>



<h3 class="wp-block-heading">3.7 Erster Login in n8n</h3>



<p>Öffne deinen Browser. Tipp ein: <code>http://DEINE-NAS-IP:5678</code> (ersetze <code>DEINE-NAS-IP</code> durch die tatsächliche IP, z. B. <code>http://192.168.178.50:5678</code>)<br>Nach ein paar Sekunden sollte sich die n8n-Oberfläche öffnen.<code>://DEINE-NAS-IP:5678</code></p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440087bcb4&quot;}" data-wp-interactive="core/image" data-wp-key="69e440087bcb4" class="wp-block-image aligncenter size-full is-resized wp-lightbox-container"><img loading="lazy" decoding="async" width="709" height="414" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/01/BILD-9-n8n-Set-up-owner-account.png" alt="n8n Ersteinrichtung: Owner-Account auf Synology NAS anlegen" class="wp-image-279" style="width:727px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/01/BILD-9-n8n-Set-up-owner-account.png 709w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-9-n8n-Set-up-owner-account-300x175.png 300w" sizes="auto, (max-width: 709px) 100vw, 709px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">Bild 9: n8n Set up owner account</figcaption></figure>



<p>Du siehst jetzt ein Formular: <strong>Set up owner account</strong><br>Hier erstellst du deinen <strong>Admin-Account</strong>:</p>



<ul class="wp-block-list">
<li><strong>E-Mail:</strong> Deine echte E-Mail-Adresse (wichtig für den Lizenzschlüssel)</li>



<li><strong>Vorname / Nachname:</strong> Kann auch ein Pseudonym sein</li>



<li><strong>Passwort:</strong> Wieder: mindestens 20 Zeichen, zufällig, sicher<br>Klick auf <strong>Sign up</strong>.</li>
</ul>



<p>n8n schickt dir jetzt eine E-Mail mit einem <strong>kostenlosen Lizenzschlüssel</strong>. Der schaltet ein paar zusätzliche Features frei (Community-Support, Templates, etc.). Du brauchst ihn nicht zwingend, aber es lohnt sich.<br>Sobald die E-Mail da ist:</p>



<ul class="wp-block-list">
<li>Geh in n8n → <strong>Settings → Usage &amp; Plan</strong></li>



<li>Trag den Lizenzschlüssel ein</li>



<li>Speichern<br>Fertig. n8n ist betriebsbereit.</li>
</ul>



<p><strong>Ulf:</strong> „Und jetzt? Was mache ich als Erstes?&#8220;<br><strong>Tanja:</strong> „Schau dich um. Klick auf <strong>Workflows → New Workflow</strong>. Zieh ein paar Nodes auf die Fläche. Probier rum. Das ist der beste Weg, um zu lernen.&#8220;<br><strong>Bernd:</strong> „Ich hab hier eine Fehlermeldung: &#8218;Your n8n server is configured to use a secure cookie…&#8216; Was soll das?&#8220;</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440087c5af&quot;}" data-wp-interactive="core/image" data-wp-key="69e440087c5af" class="wp-block-image aligncenter size-full is-resized wp-lightbox-container"><img loading="lazy" decoding="async" width="846" height="262" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/02/BILD-10-n8n-server-is-configured-to-use-a-secure-cookie.png" alt="n8n Fehlerbehebung: Server is configured to use a secure cookie – Lösung für Synology NAS" class="wp-image-495" style="width:704px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/02/BILD-10-n8n-server-is-configured-to-use-a-secure-cookie.png 846w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-10-n8n-server-is-configured-to-use-a-secure-cookie-300x93.png 300w, https://www.foundic.org/wp-content/uploads/2026/02/BILD-10-n8n-server-is-configured-to-use-a-secure-cookie-768x238.png 768w" sizes="auto, (max-width: 846px) 100vw, 846px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption"><br>Bild 10: n8n server is configured to use a secure cookie</figcaption></figure>



<p><strong>Tanja:</strong> „Das bedeutet, dass <code>N8N_SECURE_COOKIE</code> auf <code>true</code> steht, aber du kein HTTPS nutzt. Geh zurück in den Container, setz die Variable auf <code>false</code>, starte den Container neu. Dann geht&#8217;s.&#8220;<br><strong>Bernd:</strong> „Und später wieder auf <code>true</code>?&#8220;<br><strong>Tanja:</strong> „Genau. Sobald du Cloudflare oder ein SSL-Zertifikat hast.&#8220;</p>



<h2 class="wp-block-heading">4 Fazit</h2>

<p>Wenn du n8n selber hosten möchtest und zusätzlich sicheren externen Zugriff brauchst, empfehle ich dir den Artikel <a href="https://www.foundic.org/de/n8n-cloudflare-tunnel-synology-nas/">n8n mit Cloudflare Tunnel absichern</a> – die perfekte Ergänzung zu dieser Anleitung.</p>





<p><strong>Tanja</strong> lehnt sich zurück.<br>„So. Dein n8n läuft jetzt auf deiner Synology NAS. Du hast die volle Kontrolle, du zahlst nichts extra, und du kannst loslegen.&#8220;<br><strong>Ulf:</strong> „Und jetzt baue ich Workflows?&#8220;<br><strong>Tanja:</strong> „Genau. Fang klein an. Verbinde zwei Apps. Lass dir eine Benachrichtigung schicken, wenn etwas passiert. Probier die KI-Integration aus. Und wenn du nicht weiterkommst, schau in die Template-Datenbank. Da ist für fast alles schon was dabei.&#8220;<br><strong>Bernd:</strong> „Ich hab schon eine Idee. Ich will, dass n8n automatisch meine E-Mails…&#8220;<br><strong>Tanja:</strong> „Bernd. Bitte. Fang mit was Einfachem an. Sonst sitzt du morgen wieder hier und fragst, warum alles in Flammen steht.&#8220;<br><strong>Ulf:</strong> „Und wenn ich Fragen habe?&#8220;<br><strong>Tanja:</strong> „Dann schreib sie in die Kommentare unter diesem Artikel. Oder schau in die n8n-Community. Oder probier einfach. Das Schöne an Containern: Du kannst nichts kaputt machen. Schlimmstenfalls startest du neu.&#8220;</p>



<p><strong>Du hast es geschafft.</strong><br>Du hast n8n selber hosten auf deiner Synology NAS erfolgreich umgesetzt. PostgreSQL läuft (falls du dich dafür entschieden hast). Du hast einen Admin-Account und kannst loslegen.<br>Der nächste Schritt: <strong>Workflows bauen.</strong></p>



<p>Automatisiere etwas, das dich nervt<br>Und wenn du Verbesserungsvorschläge für diese Anleitung hast – oder Ideen für Workflows, die ich testen soll – <strong>schreib&#8217;s in die Kommentare.</strong><br>Viel Erfolg. Und: Hab Spaß. Automatisierung ist kein Hexenwerk. Es ist Lego für Erwachsene.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.foundic.org/de/n8n-selbst-hosten-synology-nas-docker-installation/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Eigene Website für Anfänger mit WordPress: Praktische Schritt-für-Schritt Anleitung am Beispiel von foundic.org</title>
		<link>https://www.foundic.org/de/eigene-website-mit-wordpress-fuer-anfaenger/</link>
					<comments>https://www.foundic.org/de/eigene-website-mit-wordpress-fuer-anfaenger/#respond</comments>
		
		<dc:creator><![CDATA[Michael Müller]]></dc:creator>
		<pubDate>Sun, 18 Jan 2026 16:57:25 +0000</pubDate>
				<category><![CDATA[Projekte]]></category>
		<guid isPermaLink="false">https://www.foundic.org/?p=115</guid>

					<description><![CDATA[Du möchtest eine eigene Website mit WordPress erstellen? In dieser Anleitung zeige ich dir, wie ich foundic.org mit selbst gehostetem WordPress aufgebaut habe – ohne Baukasten, ohne Agentur und mit voller Kontrolle über Inhalte, Daten und Kosten. Die Anleitung richtet sich an alle, die: Um diese Anleitung verständlicher zu machen, begleiten dich drei Personen:Die typischen [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Du möchtest eine eigene Website mit WordPress erstellen? In dieser Anleitung zeige ich dir, wie ich foundic.org mit selbst gehostetem WordPress aufgebaut habe – ohne Baukasten, ohne Agentur und mit voller Kontrolle über Inhalte, Daten und Kosten.</p>



<p>Die Anleitung richtet sich an alle, die:</p>



<ul class="wp-block-list">
<li>WordPress eigenständig betreiben möchten</li>



<li>Wert auf Datenschutz (DSGVO), Sicherheit und Nachhaltigkeit legen</li>



<li>ihre Website langfristig erweitern wollen (Blog, Projekte, Downloads, Formulare)</li>
</ul>



<p><strong>Um diese Anleitung verständlicher zu machen, begleiten dich drei Personen:</strong><br>Die typischen Büro-Charaktere: Die kompetente IT-Kollegin, der selbsternannte Experte und der ehrliche Anfänger. Diese drei Perspektiven helfen dir, typische Stolperfallen zu erkennen und WordPress wirklich zu verstehen.</p>



<p><strong>Tanja</strong>&nbsp;ist die IT-Expertin in dieser Geschichte. Sie weiß, wie WordPress funktioniert, erklärt geduldig und strukturiert – und lässt sich von schlechten Ratschlägen nicht aus der Ruhe bringen. Wenn du eine Frage hast, hat Tanja die Antwort.<br><strong>Bernd</strong>&nbsp;ist der selbsternannte „Experte&#8220;, der alles besser weiß – und meistens falsch liegt. Seine Abkürzungen und sein Halbwissen führen regelmäßig zu Problemen. Er steht für alle gefährlichen Mythen und schlechten Praktiken, die du vermeiden solltest.<br><strong>Ulf</strong>&nbsp;ist der Lernende, genau wie du. Er stellt die Fragen, die dir im Kopf herumschwirren, und braucht manchmal einen Vergleich aus dem Alltag, um IT zu verstehen. Wenn Ulf etwas nicht versteht, ist das völlig in Ordnung – dafür ist Tanja da.</p>



<p><strong>&#8222;Und… Action!&#8220;</strong></p>



<p><strong>Tanja</strong>: „Okay, heute richten wir eine WordPress-Website ein. Von Null auf Live.&#8220;<br><strong>Bernd</strong>: „WordPress? Das ist doch dieser kostenlose Blog-Kram, oder? Installier ich in fünf Minuten.&#8220;<br><strong>Ulf</strong>: „Ich hab gehört, das ist kompliziert. Braucht man da nicht so… Server und Datenbanken?&#8220;<br><strong>Tanja</strong>: „Genau die richtige Einstellung, Ulf. Ja, wir brauchen ein paar technische Grundlagen. Aber keine Panik – wir gehen Schritt für Schritt durch. Und Bernd: Wenn du in fünf Minuten fertig bist, hast du garantiert etwas übersehen.&#8220;</p>



<h2 class="wp-block-heading">1 Warum WordPress?</h2>



<p><strong>Bernd</strong>: „Warum nicht einfach WIX? Da klickst du dir was zusammen und fertig.&#8220;<br><strong>Tanja</strong>: „Weil du bei <a href="http://wix.com" target="_blank" rel="noopener">WIX.com</a> in einer Mietswohnung lebst. Bei WordPress gehört dir das Haus.&#8220;<br>Und das ist kein Marketing-Spruch. WordPress ist nicht ohne Grund das weltweit meistgenutzte Content-Management-System. Laut aktuellen Marktanalysen laufen über 40 % aller Websites auf WordPress. Es ist sowohl einsteigerfreundlich als auch langfristig skalierbar.<br>Verglichen mit anderen Content-Management-Systemen wie Joomla (komplexere Bedienung für Anfänger) oder TYPO3 (eher für große Enterprise-Projekte geeignet), punktet WordPress vor allem mit der mit Abstand größten Community und der umfangreichsten Auswahl an Plugins.<br><strong>Ulf</strong>: „Plugins? Was ist das?&#8220;<br><strong>Tanja</strong>: „Denk an Plugins wie an Werkzeuge in deinem Werkzeugkasten. Du hast eine Grundausstattung – deine Website. Und dann fügst du Werkzeuge hinzu: einen Spamfilter, ein Backup-Tool, ein Suchmaschinen-Optimierungs-Kit. Jedes Plugin erfüllt eine bestimmte Aufgabe.&#8220;<br>Genau diese Erweiterbarkeit macht den Unterschied. Während Baukastensysteme wie Wix oder Squarespace durch ihre intuitive Drag-and-Drop-Oberfläche überzeugen, sind sie bei der Suchmaschinenoptimierung und bei individuell angepassten Funktionen meist schnell am Limit. WordPress schafft hier genau die richtige Mischung aus hoher Flexibilität und gleichzeitig guter Bedienbarkeit.</p>



<p><a href="https://www.wordpress.org/" target="_blank" rel="noopener">WordPress.org</a>&nbsp;eignet sich ideal, wenn du:</p>



<ul class="wp-block-list">
<li>Inhalte künftig selbst unkompliziert pflegen möchtest</li>



<li>Die Website flexibel erweitern willst (Unterseiten, Formulare, Downloads)</li>



<li>Unabhängig von Baukasten-Anbietern bleiben möchtest</li>



<li>Eine professionelle und kosteneffiziente Lösung suchst<br>Der Mehrwert gegenüber Abo-Baukästen zeigt sich konkret in drei Bereichen:</li>



<li>Trennung von Inhalt und Design: Themes jederzeit wechselbar – als würdest du die Tapete wechseln, ohne die Möbel neu kaufen zu müssen</li>



<li>Große Plugin-Auswahl: SEO, Sicherheit, Performance, Shop</li>



<li>Volle Datenhoheit: Eigene Datenbank, eigener Server</li>
</ul>



<p><strong>Bernd</strong>: „Aber bei Wix bezahle ich doch nur 15 Euro im Monat.&#8220;<br><strong>Tanja</strong>: „Ja, solange du bleibst. Versuch mal, deine Inhalte umzuziehen. Viel Spaß dabei. Bei WordPress zahlst du fürs Hosting – etwa 5 bis 10 Euro im Monat – und behältst alles unter Kontrolle.&#8220;<br>Genau das ist der Punkt: Als Open-Source-CMS läuft WordPress bei vielen Hostern und lässt sich bei Bedarf problemlos umziehen. Langfristig fallen im Wesentlichen nur Kosten für Hosting und Domain an.<br><strong>Ulf</strong>: „Verstanden. Aber wo fange ich konkret an?&#8220;<br><strong>Tanja</strong>: „Gute Frage. Ich zeige dir 5 Schritte, mit denen du den Überblick behältst:&#8220;</p>



<ol class="wp-block-list">
<li>Die richtige WordPress‑Plattform wählen</li>



<li>WordPress manuell installieren</li>



<li>Grundlegende Seiten &amp; Design einrichten</li>



<li>Inhalte strukturieren und veröffentlichen</li>



<li>Weitere Plugins und Tools einrichten</li>
</ol>



<h2 class="wp-block-heading">2 Die richtige WordPress‑Plattform wählen</h2>



<p><strong>Ulf</strong>: „Moment. Es gibt verschiedene WordPress-Versionen?&#8220;<br><strong>Tanja</strong>: „Zwei Hauptvarianten. WordPress.com und WordPress.org. Der Unterschied ist riesig.&#8220;</p>



<h3 class="wp-block-heading">2.1 WordPress.com vs. WordPress.org</h3>



<p>Kostenlose Plattformen wie WordPress.com ermöglichen einen schnellen Einstieg ohne technische Vorkenntnisse.</p>



<p><strong>Vorteile</strong>:</p>



<ul class="wp-block-list">
<li>Schneller Start ohne technischen Aufwand</li>



<li>Hosting inklusive</li>
</ul>



<p><strong>Nachteile</strong>:</p>



<ul class="wp-block-list">
<li>Stark eingeschränkte Design- und Funktionsmöglichkeiten</li>



<li>Kaum Kontrolle über Plugins, SEO und Daten</li>



<li>Risiko: Kontosperrung oder Löschung möglich</li>
</ul>



<p><strong>Bernd</strong>: „Klingt doch super. Einfach, schnell, kostenlos.&#8220;<br><strong>Tanja</strong>: „Bis WordPress.com deine Seite offline nimmt, weil du gegen irgendeine Nutzungsbedingung verstoßen hast. Oder bis du merkst, dass du keine Plugins installieren kannst. Dann sitzt du in der Falle.&#8220; Im Gegensatz dazu steht&nbsp;<a href="https://www.wordpress.org/" target="_blank" rel="noopener">WordPress.org</a>&nbsp;(self-hosted):</p>



<p><strong>Vorteile</strong>:</p>



<ul class="wp-block-list">
<li>Das „echte&#8220; WordPress mit voller Kontrolle</li>



<li>Freie Wahl bei Themes, Plugins und Einstellungen</li>



<li>Du entscheidest, was passiert</li>
</ul>



<p><strong>Nachteile</strong>:</p>



<ul class="wp-block-list">
<li>Eigene Verantwortung für Updates, Sicherheit und Backups</li>



<li>Benötigt eigenes Webhosting (kostenpflichtig)</li>
</ul>



<p><strong>Fazit</strong>: Wenn du deine Website langfristig betreiben oder ausbauen möchtest, ist WordPress.org die deutlich nachhaltigere Lösung.</p>



<p><br><strong>Ulf</strong>: „Okay, ich will die Kontrolle. Aber was ist Hosting?&#8220;<br><strong>Tanja</strong>: „Hosting ist der Speicherplatz, auf dem deine Website liegt. Stell dir vor, deine Website ist ein Haus. Das Hosting ist das Grundstück, auf dem es steht.&#8220;</p>



<h3 class="wp-block-heading">2.2 Hosting-Optionen</h3>



<p>Es gibt zwei Hosting-Modelle:</p>



<p><strong>Klassisches Webhosting</strong>:</p>



<ul class="wp-block-list">
<li>Volle Kontrolle</li>



<li>Günstig</li>



<li>Technische Verantwortung liegt bei dir</li>
</ul>



<p><strong>Managed WordPress-Hosting</strong>:</p>



<ul class="wp-block-list">
<li>Updates, Backups, Sicherheit inklusive</li>



<li>Weniger technischer Aufwand</li>



<li>Höhere Kosten und teilweise eingeschränkte Konfigurationsfreiheit</li>
</ul>



<p><strong>Bernd</strong>: „Managed klingt doch entspannt.&#8220;<br><strong>Tanja</strong>: „Ja, aber du zahlst das Drei- bis Fünffache. Und für Anfänger reicht klassisches Hosting völlig aus.&#8220;</p>



<p>Ich habe mich für ein klassisches Webhosting bei&nbsp;<a href="https://www.strato.de/" target="_blank" rel="noopener">STRATO</a>&nbsp;entschieden, weil meine Domain dort bereits lag. Es ist nicht zwingend der „beste&#8220; Hoster, aber für meine Zwecke die pragmatischste Lösung ohne Umzugsstress.</p>



<h2 class="wp-block-heading">3 WordPress manuell installieren</h2>



<p><strong>Ulf</strong>: „Manuell? Gibt&#8217;s da nicht so einen ‚1-Klick-Installer&#8216;?&#8220;<br><strong>Tanja</strong>: „Gibt&#8217;s. Nutzen wir aber nicht.&#8220;<br><strong>Bernd</strong>: „Warum nicht? Ist doch viel schneller!&#8220;<br><strong>Tanja</strong>: „Weil du dann nicht verstehst, was passiert. Wenn später etwas schiefgeht, stehst du da und weißt nicht, wo du anfangen sollst. Wir machen das richtig – einmal, von Grund auf.&#8220;<br>Ich verzichte bewusst auf „1-Click-Installationen&#8220;, die einige Hosting-Anbieter anbieten, um:</p>



<ul class="wp-block-list">
<li>Dateirechte und Struktur vollständig zu verstehen</li>



<li>maximale Kontrolle über Sicherheit und Updates zu behalten</li>



<li>später problemlos migrieren zu können</li>
</ul>



<p>Bevor du WordPress installieren kannst, brauchst du eine Domain (deine Webadresse). Die Domain kannst du gemeinsam mit einem Hosting-Paket bei vielen Anbietern kaufen.</p>



<p><strong>Technische Mindestanforderungen</strong>, damit du das richtige Paket beim WebHoster auswählst:</p>



<ul class="wp-block-list">
<li><strong>PHP-Version</strong>: Mindestens 7.4, besser 8.2 oder höher für maximale Geschwindigkeit und Sicherheit</li>



<li><strong>Datenbank</strong>: MySQL ab Version 8.0 oder MariaDB ab Version 10.6</li>



<li><strong>Arbeitsspeicher (PHP Memory Limit)</strong>: Mindestens 256 MB, damit auch umfangreiche Plugins flüssig laufen</li>
</ul>



<p>Diese Anforderungen erfüllen nahezu alle modernen Webhoster.</p>



<p>Der folgende Installations-Prozess (entspricht dem offiziellen WordPress‑Standard):</p>



<ol class="wp-block-list">
<li>Datenbank anlegen:&nbsp;SQL-Datenbank (z. B. MariaDB) im Hoster-Panel erstellen</li>



<li>WordPress herunterladen:&nbsp;Aktuelles Paket von&nbsp;<a href="https://de.wordpress.org/download/" target="_blank" rel="noopener">WordPress.org</a>&nbsp;laden</li>



<li>WordPress hochladen (FTP):&nbsp;Mit FileZilla Dateien auf den Server laden</li>



<li>WordPress installieren: Installationsassistent im Browser folgen</li>



<li>Sicherheit erhöhen: Plugins wie Wordfence installieren</li>
</ol>



<h3 class="wp-block-heading">3.1 Datenbank anlegen</h3>



<p><strong>Ulf</strong>: „Datenbank? Klingt nach IT-Keller.&#8220;<br><strong>Tanja</strong>: „Eine Datenbank ist wie ein digitales Aktenschrank-System. Deine Website speichert dort alle Beiträge, Kommentare, Einstellungen. Ohne Datenbank keine WordPress-Website.&#8220;<br>So gehst du vor:</p>



<ol class="wp-block-list">
<li>Bei deinem Hosting-Anbieter einloggen</li>



<li>SQL Datenbank erstellen (z.B. MariaDB 10)</li>



<li>Zugangsdaten&nbsp;notieren:
<ul class="wp-block-list">
<li>Datenbankname</li>



<li>Benutzername</li>



<li>Passwort</li>



<li>Datenbank Server / Host<br><strong>Wichtig</strong>: Schreib dir diese Zugangsdaten auf. Du brauchst sie später bei der Installation.</li>
</ul>
</li>
</ol>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400886835&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400886835" class="wp-block-image aligncenter size-large is-resized wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="572" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/01/BILD-1-Screenshot-im-Hosting-Panel-Bereich-Datenbanken-anlegent-1024x572.png" alt="BILD 1 - Screenshot im Hosting-Panel - Bereich Datenbanken" class="wp-image-341" style="width:794px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/01/BILD-1-Screenshot-im-Hosting-Panel-Bereich-Datenbanken-anlegent-1024x572.png 1024w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-1-Screenshot-im-Hosting-Panel-Bereich-Datenbanken-anlegent-300x167.png 300w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-1-Screenshot-im-Hosting-Panel-Bereich-Datenbanken-anlegent-768x429.png 768w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-1-Screenshot-im-Hosting-Panel-Bereich-Datenbanken-anlegent-1536x857.png 1536w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-1-Screenshot-im-Hosting-Panel-Bereich-Datenbanken-anlegent-2048x1143.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 1 &#8211; Screenshot im Hosting-Panel &#8211; Bereich Datenbanken</figcaption></figure>



<h3 class="wp-block-heading">3.2 WordPress herunterladen</h3>



<p><strong>Bernd</strong>: „Kann ich mir WordPress nicht einfach irgendwo runterladen?&#8220;<br><strong>Tanja</strong>: „Kannst du. Aber dann riskierst du, dir eine manipulierte Version einzufangen. Geh immer zur offiziellen Quelle.&#8220;<br>So gehst du vor:</p>



<ol class="wp-block-list">
<li>Offizielle Quelle:&nbsp;<a href="https://www.wordpress.org/" target="_blank" rel="noopener">WordPress.org</a></li>



<li>Lade die ZIP-Datei über „Get WordPress&#8220; herunter</li>



<li>Entpacke die ZIP-Datei lokal auf deinem Computer<br><strong>Wichtig</strong>: Nur von der offiziellen Quelle herunterladen, um saubere Originaldateien zu erhalten und manipulierte Dateien zu vermeiden.</li>
</ol>



<h3 class="wp-block-heading">3.3 WordPress hochladen (FTP)</h3>



<p><strong>Ulf</strong>: „FTP? Was ist das jetzt wieder?&#8220;<br><strong>Tanja</strong>: „File Transfer Protocol. Ein Weg, um Dateien von deinem Computer auf den Server zu schieben. Stell dir vor, du schickst einen Umzugswagen mit Möbeln von deinem Haus zu einem anderen Haus. FTP ist der Umzugswagen.&#8220;<br>So gehst du vor:</p>



<ol class="wp-block-list">
<li>FTP-Zugangsdaten im Hosting-Anbieter Portal abrufen z.B. unter SFTP &amp; SSH bei STRATO
<ul class="wp-block-list">
<li>Server / Host (&#8222;sftp://&#8220; muss bei FileZilla vor Server stehen)</li>



<li>Port</li>



<li>Benutzername</li>



<li>Passwort</li>
</ul>
</li>



<li>SFTP-Zugang aktivieren für sicheren Upload</li>



<li>FTP‑Client (z.B. FileZilla) installieren.&nbsp;Über&nbsp;<a href="https://filezilla-project.org/" target="_blank" rel="noopener">FileZilla</a>&nbsp;kannst Du den Client kostenlos herunterladen (für macOS, Windows oder Linux)</li>



<li>Zielordner anlegen:&nbsp;Erstelle im Root-Verzeichnis des Servers einen neuen Ordner (z.B.&nbsp;<code>/foundic/</code>)
<ul class="wp-block-list">
<li>Damit deine Domain später direkt auf dieses Verzeichnis zeigen kann</li>



<li>In FileZilla: Rechtsklick → &#8222;Verzeichnis erstellen&#8220;</li>
</ul>
</li>



<li>Alle entpackten WordPress-Dateien hochladen:&nbsp;Ziehe alle entpackten WordPress-Dateien per Drag &amp; Drop in den neuen Ordner
<ul class="wp-block-list">
<li>Dauer: ca. 3-10 Minuten je nach Verbindung</li>
</ul>
</li>



<li>Struktur prüfen:&nbsp;Dein Verzeichnis sollte nun enthalten:
<ul class="wp-block-list">
<li><code>/wp-admin/</code></li>



<li><code>/wp-content/</code></li>



<li><code>/wp-includes/</code></li>



<li>Dateien wie&nbsp;<code>index.php</code>,&nbsp;<code>wp-login.php</code>,&nbsp;<code>wp-config-sample.php</code></li>
</ul>
</li>
</ol>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e44008873d5&quot;}" data-wp-interactive="core/image" data-wp-key="69e44008873d5" class="wp-block-image aligncenter size-large is-resized wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="825" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/01/BILD-2-Ansicht-von-FileZilla-mit-korrekter-Ordnerstruktur-im-Zielverzeichnis-1024x825.png" alt="BILD 2 - Ansicht von FileZilla, mit korrekter Ordnerstruktur im Zielverzeichnis" class="wp-image-343" style="aspect-ratio:1.241224157325162;width:812px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/01/BILD-2-Ansicht-von-FileZilla-mit-korrekter-Ordnerstruktur-im-Zielverzeichnis-1024x825.png 1024w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-2-Ansicht-von-FileZilla-mit-korrekter-Ordnerstruktur-im-Zielverzeichnis-300x242.png 300w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-2-Ansicht-von-FileZilla-mit-korrekter-Ordnerstruktur-im-Zielverzeichnis-768x619.png 768w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-2-Ansicht-von-FileZilla-mit-korrekter-Ordnerstruktur-im-Zielverzeichnis-1536x1237.png 1536w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-2-Ansicht-von-FileZilla-mit-korrekter-Ordnerstruktur-im-Zielverzeichnis-2048x1650.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 2 &#8211; Ansicht von FileZilla, mit korrekter Ordnerstruktur im Zielverzeichnis</figcaption></figure>



<ol start="7" class="wp-block-list">
<li>Domain verbinden:&nbsp;In der Domainverwaltung die Domain auf das Stammverzeichnis setzen
<ul class="wp-block-list">
<li>Bei STRATO: Paket-Verwaltung → Domains → Domain auswählen → &#8222;Verwalten&#8220;</li>



<li>Unter &#8222;Ziel der Domain&#8220; auf &#8222;Intern&#8220; umstellen</li>



<li>Pfad eingeben:&nbsp;<code>/foundic/</code>&nbsp;(dein angelegter Ordner)</li>



<li>Speichern – die Domain zeigt nun auf dein WordPress-Verzeichnis</li>
</ul>
</li>
</ol>



<figure class="wp-block-image aligncenter size-large is-resized"><a href="https://www.foundic.org/?attachment_id=344"><img loading="lazy" decoding="async" width="1024" height="887" src="https://www.foundic.org/wp-content/uploads/2026/01/BILD-3-Screenshot-Domainverwaltung-beim-Hoster-–-Einstellung-1024x887.png" alt="BILD 3 - Screenshot Domainverwaltung beim Hoster – Einstellung" class="wp-image-344" style="aspect-ratio:1.1544636253765537;width:802px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/01/BILD-3-Screenshot-Domainverwaltung-beim-Hoster-–-Einstellung-1024x887.png 1024w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-3-Screenshot-Domainverwaltung-beim-Hoster-–-Einstellung-300x260.png 300w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-3-Screenshot-Domainverwaltung-beim-Hoster-–-Einstellung-768x665.png 768w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-3-Screenshot-Domainverwaltung-beim-Hoster-–-Einstellung.png 1434w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">BILD 3 &#8211; Screenshot Domainverwaltung beim Hoster – Einstellung</figcaption></figure>



<p>Falls der Installationsassistent einmal hakt: Du kannst die Datei&nbsp;<code>wp-config-sample.php</code>&nbsp;manuell in&nbsp;<code>wp-config.php</code>&nbsp;umbenennen und deine Datenbankdaten direkt dort eintragen, bevor du sie per FTP hochlädst.</p>



<h3 class="wp-block-heading">3.4 WordPress installieren</h3>



<p><strong>Tanja</strong>: „Jetzt kommt der entspannte Teil. WordPress macht den Rest fast von allein.&#8220;<br><strong>Bernd</strong>: „Hätte man das nicht gleich so machen können?&#8220;<br><strong>Tanja</strong>: „Bernd, wir haben gerade die Grundmauern gelegt. Jetzt kommt der Innenausbau.&#8220;<br>So gehst du vor:</p>



<ol class="wp-block-list">
<li>Öffne deinen Browser und rufe deine Domain auf (z.B.&nbsp;<code>https://foundic.org</code>)</li>



<li>Der Installationsassistent startet automatisch</li>



<li>Wähle die Sprache aus</li>



<li>Gib die Datenbankdaten aus Schritt 1 ein</li>



<li>Lege einen neuen WordPress-Admin-Benutzer an
<ul class="wp-block-list">
<li><strong>Sicherheitshinweis</strong>:&nbsp;Verwende ein neues, starkes Passwort</li>
</ul>
</li>



<li>Melde dich erstmalig an über&nbsp;<code>https://deine-domain.de/wp-login.php</code><br>Erste Einstellungen nach der Installation</li>



<li>Updates prüfen&nbsp;Dashboard → Aktualisierungen: Prüfe, ob WordPress und Plugins aktuell sind</li>



<li>Permalinks optimieren&nbsp;Einstellungen → Permalinks → &#8222;Beitragsname&#8220; auswählen
<ul class="wp-block-list">
<li>Bessere Lesbarkeit für Besucher</li>



<li>Verbessert SEO (Suchmaschinenoptimierung)</li>
</ul>
</li>
</ol>



<p><strong>Ulf</strong>: „Permalinks? Was ist das?&#8220;<br><strong>Tanja</strong>: „Die URLs deiner Beiträge. Standardmäßig sieht das so aus:&nbsp;<code>deine-seite.de/?p=123</code>. Mit Permalinks wird daraus:&nbsp;<code>deine-seite.de/mein-erster-beitrag</code>. Viel lesbarer, besser für Google.&#8220;</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400887f46&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400887f46" class="wp-block-image aligncenter size-large is-resized wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="802" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/01/BILD-4-Screenshot-WordPress-Backend-Einstellungen-→-Permalinks-1024x802.png" alt="BILD 4 - Screenshot WordPress-Backend - Einstellungen → Permalinks" class="wp-image-345" style="width:822px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/01/BILD-4-Screenshot-WordPress-Backend-Einstellungen-→-Permalinks-1024x802.png 1024w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-4-Screenshot-WordPress-Backend-Einstellungen-→-Permalinks-300x235.png 300w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-4-Screenshot-WordPress-Backend-Einstellungen-→-Permalinks-768x601.png 768w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-4-Screenshot-WordPress-Backend-Einstellungen-→-Permalinks.png 1434w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 4 &#8211; Screenshot WordPress-Backend &#8211; Einstellungen → Permalinks</figcaption></figure>



<ol start="9" class="wp-block-list">
<li>Unnötige Plugins entfernen&nbsp;Plugins → Deaktivieren und löschen von:
<ul class="wp-block-list">
<li>&#8222;Hello Dolly&#8220;</li>



<li>&#8222;Akismet&#8220; (falls nicht benötigt)</li>



<li>Je weniger Plugins, desto schneller und sicherer</li>
</ul>
</li>



<li>Öffentlichen Namen festlegen&nbsp;Benutzer → Dein Profil → Spitznamen eintragen → Als &#8222;Öffentlicher Name&#8220; auswählen</li>
</ol>



<h3 class="wp-block-heading">3.5 Sicherheit erhöhen</h3>



<p><strong>Bernd</strong>: „Sicherheit? Wer will denn meine Website hacken?&#8220;<br><strong>Tanja</strong>: „Niemand persönlich. Aber es gibt automatisierte Bots, die täglich tausende WordPress-Seiten durchscannen und versuchen, sich einzuloggen. Wenn du keine Sicherheitsvorkehrungen triffst, bist du ein leichtes Ziel.&#8220;<br>So gehst du vor:</p>



<ol class="wp-block-list">
<li>Plugin &#8222;<a href="https://wordpress.org/plugins/" target="_blank" rel="noopener">Wordfence Security</a>&#8220; installieren
<ul class="wp-block-list">
<li>Plugin installieren und aktivieren</li>



<li>Kostenlose Lizenz unter&nbsp;<a href="https://www.wordfence.com/" target="_blank" rel="noopener">wordfence.com</a></li>



<li>Brute-Force-Protection in der Free-Version auf 100% setzen</li>
</ul>
</li>
</ol>



<p><strong>Ulf</strong>: „Brute-Force? Klingt nach Einbrecher.&#8220;<br><strong>Tanja</strong>: „Ist es auch. Brute-Force heißt: Ein Bot probiert tausende Passwörter durch, bis er reinkommt. Wordfence blockt solche Versuche.&#8220;</p>



<ol start="2" class="wp-block-list">
<li>Plugin &#8220; <a href="https://wordpress.org/plugins/" target="_blank" rel="noopener">UpdraftPlus</a>&#8220; für Backups
<ul class="wp-block-list">
<li>Plugin installieren und aktivieren</li>



<li>Einstellungen → Rhythmus und Speicherort wählen (z.B. Google Drive)</li>
</ul>
</li>



<li>Plugin <a href="https://wordpress.org/plugins/" target="_blank" rel="noopener">Antispam Bee</a>
<ul class="wp-block-list">
<li>Datenschutzfreundliche, lokale Spam-Lösung (keine Datenübertragung in die USA)</li>



<li>Meine Einstellungen:
<ul class="wp-block-list">
<li>Kommentare nur in Deutsch und Englisch zulassen</li>



<li>Spam nach 30 Tagen automatisch löschen</li>



<li>Spam-Zähler im Dashboard aktivieren</li>
</ul>
</li>
</ul>
</li>



<li>Plugins <a href="https://wordpress.org/plugins/" target="_blank" rel="noopener">WPS Hide Login</a>
<ul class="wp-block-list">
<li>Verändert die Standard-Login-URL von&nbsp;<code>/wp-login.php</code>&nbsp;zu einer individuellen URL (z.B.&nbsp;<code>/mein-geheimer-login</code>)</li>



<li>Einstellungen → Allgemein → WPS Hide Login</li>
</ul>
</li>
</ol>



<p><strong>Bernd</strong>: „Warum die Login-URL verstecken?&#8220;<br><strong>Tanja</strong>: „Weil jeder Bot weiß, dass WordPress-Seiten unter&nbsp;<code>/wp-login.php</code>&nbsp;erreichbar sind. Wenn du die URL änderst, laufen die meisten Angriffe ins Leere.&#8220;</p>



<ol start="5" class="wp-block-list">
<li>HTTPS prüfen&nbsp;Einstellungen → Allgemein: Stelle sicher, dass beide URLs mit&nbsp;<code>https://</code>&nbsp;beginnen:
<ul class="wp-block-list">
<li>WordPress-Adresse (URL)</li>



<li>Website-Adresse (URL).</li>
</ul>
</li>
</ol>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400888c21&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400888c21" class="wp-block-image aligncenter size-large is-resized wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="802" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/01/BILD-5-Screenshot-WordPress-Backend-Einstellungen-→-Allgemein-1024x802.png" alt="BILD 5 - Screenshot WordPress-Backend - Einstellungen → Allgemein" class="wp-image-346" style="width:800px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/01/BILD-5-Screenshot-WordPress-Backend-Einstellungen-→-Allgemein-1024x802.png 1024w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-5-Screenshot-WordPress-Backend-Einstellungen-→-Allgemein-300x235.png 300w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-5-Screenshot-WordPress-Backend-Einstellungen-→-Allgemein-768x602.png 768w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-5-Screenshot-WordPress-Backend-Einstellungen-→-Allgemein.png 1433w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 5 &#8211; Screenshot WordPress-Backend &#8211; Einstellungen → Allgemein</figcaption></figure>



<h2 class="wp-block-heading">4 Grundlegende Seiten &amp; Design einrichten</h2>



<p><strong>Tanja</strong>: „Technik steht. Jetzt kommt die Optik.&#8220;<br><strong>Ulf</strong>: „Endlich! Ich will, dass das Ding gut aussieht.&#8220;<br><strong>Bernd</strong>: „Ich nehm einfach irgendein Theme. Sind doch eh alle gleich.&#8220;<br><strong>Tanja</strong>: „Falsch. Es gibt Themes, die sind schnell, sauber und anpassbar. Und es gibt Themes, die sind vollgestopft mit unnötigem Code, verlangsamen deine Seite und sind ein Albtraum, wenn du etwas ändern willst.&#8220;<br>Ich nutze das&nbsp;<a href="https://www.wpastra.com" target="_blank" rel="noopener">Astra</a> Theme, da es schnell und extrem anpassbar ist.<br>Die ersten Seiten:</p>



<ol class="wp-block-list">
<li>Das Design wählen (Theme):&nbsp;Astra-Theme installieren und DSGVO-konform konfigurieren</li>



<li>Rechtliche Pflichtseiten erstellen:&nbsp;Impressum und Datenschutzseite erstellen</li>



<li>&#8222;Test-Daten&#8220; entfernen:&nbsp;aus WordPress</li>
</ol>



<h3 class="wp-block-heading">4.1 Das Design (Theme) wählen</h3>



<p>Theme installieren&nbsp;Design → Themes → Theme hinzufügen → &#8222;Astra&#8220; suchen → Installieren und aktivieren</p>



<p><strong>Meine Astra-Einstellungen:</strong></p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th><strong>Bereich</strong></th><th><strong>Einstellung</strong></th><th><strong>Wert</strong></th></tr></thead><tbody><tr><td>Farben</td><td>Akzent / Überschriften</td><td><code>#111827</code>&nbsp;(Edles Schwarz)</td></tr><tr><td>Farben</td><td>Links</td><td><code>#2563EB</code>&nbsp;(Modernes Blau), <code>#1D4ED8</code> (leicht stärkeres Blau)</td></tr><tr><td>Hintergrund</td><td>Website-Hintergrund</td><td><code>#F5F6F7</code>&nbsp;(Hellgrau)</td></tr><tr><td>Typografie</td><td>Überschriften</td><td>Inter, Sans-Serif (Stärke 800)</td></tr><tr><td>Leistung</td><td>Google Fonts</td><td>Lokal laden (Wichtig für DSGVO!)</td></tr></tbody></table></figure>



<p>DSGVO-Warnung zu Google Fonts:&nbsp;Wenn Google Fonts aus den USA geladen werden, wird die IP-Adresse des Besuchers übertragen (Urteil LG München I, 20.01.2022, Az. 3 O 17493/20). Prüfe deine Seite mit dem&nbsp;Google Fonts Checker wie https://sicher3.de/google-fonts-checker/.</p>



<p>Notwendige Anpassungen:</p>



<ol class="wp-block-list">
<li>DSGVO-konforme Schriften
<ul class="wp-block-list">
<li>Astra → Dashboard → Einstellungen → Leistung → &#8222;Google Fonts lokal laden&#8220; aktivieren</li>
</ul>
</li>
</ol>



<p><strong>Ulf</strong>: „Warum lokal laden?&#8220;<br><strong>Tanja</strong>: „Weil Google Fonts standardmäßig von Google-Servern geladen werden. Dabei wird die IP-Adresse deiner Besucher an Google übertragen – ein DSGVO-Verstoß. Wenn du die Schriften lokal lädst, bleiben die Daten bei dir.&#8220;</p>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e44008894c6&quot;}" data-wp-interactive="core/image" data-wp-key="69e44008894c6" class="wp-block-image aligncenter size-large is-resized wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="675" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/01/BILD-6-Screenshot-der-Astra-Einstellungen-im-WordPress-Dashboard-Google-Fonts-lokal-1024x675.png" alt="BILD 6 - Screenshot der Astra-Einstellungen im WordPress-Dashboard - Google Fonts lokal" class="wp-image-347" style="aspect-ratio:1.517055016948349;width:806px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/01/BILD-6-Screenshot-der-Astra-Einstellungen-im-WordPress-Dashboard-Google-Fonts-lokal-1024x675.png 1024w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-6-Screenshot-der-Astra-Einstellungen-im-WordPress-Dashboard-Google-Fonts-lokal-300x198.png 300w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-6-Screenshot-der-Astra-Einstellungen-im-WordPress-Dashboard-Google-Fonts-lokal-768x507.png 768w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-6-Screenshot-der-Astra-Einstellungen-im-WordPress-Dashboard-Google-Fonts-lokal.png 1281w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 6 &#8211; Screenshot der Astra-Einstellungen im WordPress-Dashboard &#8211; Google Fonts lokal</figcaption></figure>



<ol start="2" class="wp-block-list">
<li>Container-Layout
<ul class="wp-block-list">
<li>Design → Customizer → Global → Container: &#8222;Box-Layout&#8220;, 1200px / 1000px</li>
</ul>
</li>



<li>Farbschema
<ul class="wp-block-list">
<li>Design → Customizer → Global → Farben
<ul class="wp-block-list">
<li>Akzent:&nbsp;<code>#111827</code>(Edles Schwarz)</li>



<li>Links:&nbsp;<code>#2563EB</code>(Modernes Blau), <code>#1D4ED8</code> (leicht stärkeres Blau)</li>



<li>Überschriften:&nbsp;<code>#111827</code>(Edles Schwarz)</li>



<li>Website-Hintergrund:&nbsp;<code>#F5F6F7</code>(Hellgrau)</li>



<li>Hintergrund des Inhalts: <code>#FFFFFF</code>(Weiß)</li>
</ul>
</li>
</ul>
</li>



<li>Schriftzeichen
<ul class="wp-block-list">
<li>Design → Customizer → Global → Typografie
<ul class="wp-block-list">
<li>Schrift für die Überschrift: Inter, Sans-Serif / 15px / 800</li>



<li>H1-Schrift: 30px (von 64px)</li>



<li>H2-Schrift 27px (von 48px)</li>



<li>H3-Schrift 24px (von 24px)</li>



<li>H4-Schrift 21 px (von 20px)</li>
</ul>
</li>
</ul>
</li>



<li>Header anpassen
<ul class="wp-block-list">
<li>Design → Customizer → Header
<ul class="wp-block-list">
<li>Website-Titel: FOUNDIC.org</li>



<li>Titelfarbe:&nbsp;<code>#2563EB</code>(dezentes Blau), <code>#1D4ED8</code>(leicht stärkers Blau)</li>



<li>Rand oben: 1px, Farbe&nbsp;<code>#E0E0E0</code>(leichtes Grau)</li>



<li>Astra Logo kann entfernt werden und später eigenes ergänzt werden</li>
</ul>
</li>
</ul>
</li>



<li>Footer anpassen
<ul class="wp-block-list">
<li>Design → Customizer → Footer
<ul class="wp-block-list">
<li>Rand oben: 1px, Farbe&nbsp;<code>#E0E0E0</code>(leichtes Grau)</li>
</ul>
</li>
</ul>
</li>



<li>Zusätzliches CSS
<ul class="wp-block-list">
<li>Das „Feintuning“ über CSS Code:</li>
</ul>
</li>
</ol>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e4400889eef&quot;}" data-wp-interactive="core/image" data-wp-key="69e4400889eef" class="wp-block-image aligncenter size-large is-resized wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="706" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/01/BILD-7-Screenshot-WordPress-Customizer-Zusaetzliches-CSS-1024x706.png" alt="BILD 7 - Screenshot WordPress - Customizer - Zusätzliches CSS" class="wp-image-348" style="width:802px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/01/BILD-7-Screenshot-WordPress-Customizer-Zusaetzliches-CSS-1024x706.png 1024w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-7-Screenshot-WordPress-Customizer-Zusaetzliches-CSS-300x207.png 300w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-7-Screenshot-WordPress-Customizer-Zusaetzliches-CSS-768x529.png 768w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-7-Screenshot-WordPress-Customizer-Zusaetzliches-CSS.png 1223w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 7 &#8211; Screenshot WordPress &#8211; Customizer &#8211; Zusätzliches CSS</figcaption></figure>



<pre class="wp-block-code"><code>/* 1. Synchronisation: Gleicher Zeilenabstand für Absätze und Listenpunkte */
.entry-content p, 
.entry-content ul li, 
.entry-content ol li {
    line-height: 1.6; /* Gleicht den Zeilenabstand an */
    margin-bottom: 0;   /* Entfernt den extra Platz zwischen den einzelnen Listenpunkten */
}

/* 2. Absatz-Design: Festlegen des Standard-Abstands nach einem Textblock */
.entry-content p {
    margin-bottom: 1em; /* Dies ist dein "normaler" Textabstand zwischen Absätzen */
}

/* 3. Listen-Reset: Theme-eigene Abstände der Liste nach oben/unten entfernen */
.entry-content ul, 
.entry-content ol {
    margin-top: 0;
    margin-bottom: 1em; /* Gleicher Abstand nach der Liste wie nach einem Absatz */
}

/* 4. Präzisions-Korrektur: Abstand VOR dem Start der Liste */
/* Wenn eine Liste direkt auf einen Absatz folgt, wird der Abstand so reduziert, 
   dass er optisch exakt dem Abstand zwischen zwei Text-Absätzen entspricht. */
.entry-content p + ul, 
.entry-content p + ol {
    margin-top: -0.5em; /* Verringert den Abstand zum Einleitungstext */
}

/* 5. Interner Listen-Abstand: Polsterung der Listenpunkte neutralisieren */
.entry-content li {
    padding-bottom: 0;
    margin-top: 0;
}</code></pre>



<p><strong>Ulf</strong>:&nbsp;„Warum so viel CSS-Gefrickel?&#8220;&nbsp;<br><strong>Tanja</strong>:&nbsp;„Weil WordPress-Themes oft eigene Abstände mitbringen,&nbsp;die nicht immer harmonisch aussehen. Mit diesem Code sorgen wir dafür,&nbsp;dass Listen und Absätze optisch gleichmäßig wirken – wie in einem professionell gesetzten Buch.&#8220;</p>



<h3 class="wp-block-heading">4.2 Rechtliche Pflichtseiten erstellen</h3>



<p><strong>Bernd</strong>:&nbsp;„Braucht man das wirklich?&#8220;<br><strong>Tanja</strong>:&nbsp;„Ja. In Deutschland ist ein Impressum gesetzlich vorgeschrieben. Ohne Impressum riskierst du Abmahnungen. Und die kosten schnell mehrere hundert Euro.&#8220;<br>Jeder Internetauftritt in Deutschland benötigt ein Impressum und eine Datenschutzerklärung.</p>



<h4 class="wp-block-heading">4.2.1 Impressum erstellen</h4>



<p>Stelle sicher, dass dein Impressum folgende Angaben enthält, um rechtssicher zu sein:</p>



<ul class="wp-block-list">
<li>Vollständiger Name und Anschrift (kein Postfach)</li>



<li>Schnelle Kontaktmöglichkeit (E-Mail-Adresse und Telefonnummer)</li>



<li>Bei Unternehmen: Rechtsform, Vertretungsberechtigte und Registernummer/Registergericht</li>



<li>Falls vorhanden: Umsatzsteuer-Identifikationsnummer (USt-IdNr.)</li>



<li>Für journalistische Inhalte: Name eines inhaltlich Verantwortlichen</li>
</ul>



<p>Ich bin folgendermaßen vorgegangen:</p>



<ol class="wp-block-list">
<li>Entwurf mit <a href="https://www.e-recht24.de" target="_blank" rel="noopener">https://www.e-recht24.de</a> -&gt; Impressumsgenerator erstellt</li>



<li>WordPress: Seiten → Seite hinzufügen</li>



<li>Titel: &#8222;Impressum&#8220;</li>



<li>Text einfügen und veröffentlichen</li>
</ol>



<h4 class="wp-block-heading">4.2.2 Datenschutzerklärung erstellen</h4>



<ol class="wp-block-list">
<li>Erstelle einen Entwurf mit zum Beispiel&nbsp;einem Datenschutz-Generator von https://datenschutz-generator.de/</li>



<li>Erwähne alle installierten Plugins (Wordfence, UpdraftPlus, Antispam Bee, WPS Hide Login)</li>



<li>Gib deinen Hoster an</li>



<li>WordPress: Seiten → Seite hinzufügen</li>



<li>Titel: &#8222;Datenschutz&#8220;</li>



<li>Text einfügen und veröffentlichen</li>
</ol>



<h4 class="wp-block-heading">4.2.3 Footer-Menü Impressum und Datenschutz aufnehmen</h4>



<ol class="wp-block-list">
<li>Design → Menüs → &#8222;Neues Menü erstellen&#8220;</li>



<li>Name: &#8222;Footer&#8220;</li>



<li>Seiten hinzufügen: Impressum und Datenschutz</li>



<li>Position: &#8222;Footer-Menü&#8220; auswählen</li>



<li>Menü speichern</li>
</ol>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440088a9d8&quot;}" data-wp-interactive="core/image" data-wp-key="69e440088a9d8" class="wp-block-image aligncenter size-large is-resized wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="717" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/01/BILD-8-Screenshot-WordPress-Backend-Design-→-Menues-mit-Menueposition-Footer-Menue-1024x717.png" alt="BILD 8 - Screenshot WordPress-Backend - Design → Menüs mit Menüposition Footer-Menü" class="wp-image-350" style="aspect-ratio:1.4281888779791128;width:800px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/01/BILD-8-Screenshot-WordPress-Backend-Design-→-Menues-mit-Menueposition-Footer-Menue-1024x717.png 1024w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-8-Screenshot-WordPress-Backend-Design-→-Menues-mit-Menueposition-Footer-Menue-300x210.png 300w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-8-Screenshot-WordPress-Backend-Design-→-Menues-mit-Menueposition-Footer-Menue-768x538.png 768w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-8-Screenshot-WordPress-Backend-Design-→-Menues-mit-Menueposition-Footer-Menue.png 1478w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 8 &#8211; Screenshot WordPress-Backend &#8211; Design → Menüs mit Menüposition Footer-Menü</figcaption></figure>



<ol start="6" class="wp-block-list">
<li>Copyright-Zeile anpassen:&nbsp;Design → Customizer → Footer → Copyright</li>



<li>Ersetze &#8222;Powered by…&#8220; durch:<br><code>&lt;span style="font-size: 12pt;"&gt;Copyright [copyright] [current_year] [site_title] | &lt;a href="/impressum/"&gt;Impressum&lt;/a&gt;&amp;nbsp;| &lt;a href="/datenschutz/"&gt;Datenschutz&lt;/a&gt;&lt;/span&gt;</code></li>
</ol>



<h3 class="wp-block-heading">4.3 &#8222;Test-Daten&#8220; entfernen</h3>



<p>WordPress liefert Beispiel-Inhalte mit, die gelöscht werden sollten:</p>



<ul class="wp-block-list">
<li>Seiten → Alle Beispiel-Seiten in den Papierkorb</li>



<li>Beiträge → Alle Beispiel-Beiträge in den Papierkorb</li>
</ul>



<p><strong>Bernd</strong>: „Warum löschen? Vielleicht brauche ich die noch.&#8220;<br><strong>Tanja</strong>: „Du brauchst sie nicht. Das sind nur Platzhalter. Wenn du sie nicht löschst, tauchen sie in deinem Archiv auf – und das sieht unprofessionell aus.&#8220;</p>



<h2 class="wp-block-heading">5 Inhalte strukturieren und veröffentlichen</h2>



<p><strong>Ulf</strong>: „Jetzt geht&#8217;s los! Ich will Artikel schreiben!&#8220;<br><strong>Tanja</strong>: „Moment. Bevor du losschreibst, müssen wir die Struktur klären. WordPress unterscheidet zwischen Seiten und Beiträgen. Das ist wichtig.&#8220;<br><strong>Ulf</strong>: „Wo ist der Unterschied?&#8220;<br><strong>Tanja</strong>: „Seiten sind für statische Inhalte – Impressum, Datenschutz, Über uns. Die erstellst du einmal und änderst sie selten. Sie stehen immer an derselben Stelle, tauchen nicht chronologisch auf und haben kein Datum. Beiträge dagegen sind dein Blog. Sie erscheinen chronologisch auf deiner Startseite, werden in Kategorien sortiert und signalisieren Google: Diese Seite lebt, hier passiert was.&#8220;<br><strong>Ulf</strong>: „Also Seiten wie Regale im Laden, Beiträge wie wöchentliche Angebote?&#8220;<br><strong>Tanja</strong>: „Perfekte Analogie. Genau so. Die Regale bleiben, die Angebote wechseln.&#8220;</p>



<p>Diese Trennung ist ein zentraler Vorteil gegenüber vielen Baukästen – und entscheidend für dein SEO-Ranking. Suchmaschinen bevorzugen frischen Content, und Beiträge liefern genau das.</p>



<p>Mein Ziel ist es, dass alle Beiträge chronologisch auf der Startseite erscheinen und zusätzlich in Kategorien organisiert werden.</p>



<ul class="wp-block-list">
<li>Startseiten-Einstellung:&nbsp;Einstellungen → Lesen → &#8222;Deine letzten Beiträge&#8220; auswählen → Änderungen speichern</li>
</ul>



<p>Die Checkliste für die Installation:</p>



<ol class="wp-block-list">
<li>Kategorien anlegen:&nbsp;Kategorien &#8222;Redaktionelle Beiträge&#8220; und &#8222;Projekt&#8220; anlegen</li>



<li>Menü korrekt verlinken:&nbsp;Kategorien im Menü zuordnen und sortieren</li>



<li>Dein erster Beitrag:&nbsp;Beiträge erstellen, kategorisieren und Bilder hinzufügen</li>



<li>Eine einfache Suche installieren: Suchfunktion im Header einrichten, optional Relevanssi-Plugin</li>
</ol>



<h3 class="wp-block-heading">5.1 Kategorien anlegen</h3>



<p>Beiträge → Kategorien → Neue Kategorien erstellen:</p>



<ul class="wp-block-list">
<li>&#8222;Redaktionelle Beiträge&#8220; (Titelform:&nbsp;beitraege)</li>



<li>&#8222;Projekt&#8220; (Titelform:&nbsp;projekte)</li>



<li>Standard-Kategorie &#8222;Allgemein&#8220; umbenennen in &#8222;Startseite&#8220;</li>
</ul>



<p><strong>Ulf</strong>: „Titelform? Was ist das?&#8220;<br><strong>Tanja</strong>: „Das ist der Teil, der in der URL auftaucht. Aus ‚Redaktionelle Beiträge&#8216; wird in der URL ‚beitraege&#8216;. Sieht sauberer aus und ist besser für SEO.&#8220;</p>



<h3 class="wp-block-heading">5.2 Menü korrekt verlinken</h3>



<p><strong>Ulf</strong>: „Ich hab Kategorien angelegt. Wie kommen die jetzt ins Menü?&#8220;<br><strong>Tanja</strong>: „Gute Frage. WordPress fügt Kategorien nicht automatisch ins Menü ein – das musst du manuell machen.&#8220;<br><strong>Bernd</strong>: „Warum nicht automatisch? Wäre doch praktisch.&#8220;<br><strong>Tanja</strong>: „Weil du vielleicht nicht alle Kategorien im Menü haben willst. Du behältst die Kontrolle.&#8220;</p>



<p>Design → Menüs → Kategorien → &#8222;Alle anzeigen&#8220;</p>



<ul class="wp-block-list">
<li>Kategorien auswählen und &#8222;Zum Menü hinzufügen&#8220;</li>



<li>Per Drag &amp; Drop sortieren</li>



<li>Menü speichern</li>
</ul>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440088b5a0&quot;}" data-wp-interactive="core/image" data-wp-key="69e440088b5a0" class="wp-block-image aligncenter size-large is-resized wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="721" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/01/BILD-9-Screenshot-WordPress-Backend-Design-→-Menues-mit-der-Struktur-der-Hauptnavigation-1024x721.png" alt="BILD 9 - Screenshot WordPress-Backend - Design → Menüs mit der Struktur der Hauptnavigation" class="wp-image-351" style="aspect-ratio:1.420265412098886;width:804px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/01/BILD-9-Screenshot-WordPress-Backend-Design-→-Menues-mit-der-Struktur-der-Hauptnavigation-1024x721.png 1024w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-9-Screenshot-WordPress-Backend-Design-→-Menues-mit-der-Struktur-der-Hauptnavigation-300x211.png 300w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-9-Screenshot-WordPress-Backend-Design-→-Menues-mit-der-Struktur-der-Hauptnavigation-768x540.png 768w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-9-Screenshot-WordPress-Backend-Design-→-Menues-mit-der-Struktur-der-Hauptnavigation.png 1478w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 9 &#8211; Screenshot WordPress-Backend &#8211; Design → Menüs mit der Struktur der Hauptnavigation</figcaption></figure>



<h3 class="wp-block-heading">5.3 Dein erster Beitrag</h3>



<p><strong>Ulf</strong>: „Okay, jetzt will ich endlich schreiben!&#8220;<br><strong>Tanja</strong>: „Los geht&#8217;s. Der Beitrags-Editor heißt übrigens Gutenberg – benannt nach dem Erfinder des Buchdrucks.&#8220;<br><strong>Bernd</strong>: „Warum so kompliziert? Einfach Text reinhauen und fertig.&#8220;<br><strong>Tanja</strong>: „Fast. Aber ein paar Dinge solltest du beachten, damit der Beitrag auch richtig kategorisiert wird.&#8220;</p>



<p>Beiträge → Beitrag hinzufügen (im Beitrags-Editor auch &#8222;Gutenberg&#8220; genannt)</p>



<ul class="wp-block-list">
<li>Titel eingeben</li>



<li>Text schreiben</li>



<li>Kategorie auswählen (rechte Seitenleiste weiter unten)</li>



<li>Optional: Beitragsbild festlegen (rechte Seitenleiste → Beitragsbild)</li>



<li>Veröffentlichen (siehe <a href="https://www.foundic.org/mein-erster-beitrag-mit-dummy-text/">https://www.foundic.org/mein-erster-beitrag-mit-dummy-text/</a>)</li>
</ul>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440088bca6&quot;}" data-wp-interactive="core/image" data-wp-key="69e440088bca6" class="wp-block-image aligncenter size-large is-resized wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="820" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/01/BILD-10-Screenshot-Beitrag-Editor-Gutenberg-–-rechte-Seitenleiste-mit-„Kategorien-und-Option-„Beitragsbild-festlegen-1-1024x820.png" alt="BILD 10 - Screenshot Beitrag-Editor (Gutenberg) – rechte Seitenleiste mit „Kategorien“ und Option „Beitragsbild festlegen“" class="wp-image-356" style="width:798px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/01/BILD-10-Screenshot-Beitrag-Editor-Gutenberg-–-rechte-Seitenleiste-mit-„Kategorien-und-Option-„Beitragsbild-festlegen-1-1024x820.png 1024w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-10-Screenshot-Beitrag-Editor-Gutenberg-–-rechte-Seitenleiste-mit-„Kategorien-und-Option-„Beitragsbild-festlegen-1-300x240.png 300w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-10-Screenshot-Beitrag-Editor-Gutenberg-–-rechte-Seitenleiste-mit-„Kategorien-und-Option-„Beitragsbild-festlegen-1-768x615.png 768w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-10-Screenshot-Beitrag-Editor-Gutenberg-–-rechte-Seitenleiste-mit-„Kategorien-und-Option-„Beitragsbild-festlegen-1.png 1525w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 10 &#8211; Screenshot Beitrag-Editor (Gutenberg) – rechte Seitenleiste mit „Kategorien“ und Option „Beitragsbild festlegen“</figcaption></figure>



<p>Beitrags-Layout anpassen von Raster zu Liste: Design → Customizer → Inhaltstypen → Blog/Archive → Blog-Layout: &#8222;Liste&#8220; für vertikale Anordnung</p>



<p>Beitragsbild zusätzlich auf Einzelseite anzeigen:&nbsp;Design → Customizer → Inhaltstypen → Einzelbeitrag → Struktur → &#8222;Beitragsbild&#8220; aktivieren</p>



<p><strong>Bernd</strong>: „Warum das Beitragsbild zweimal einstellen?&#8220;<br><strong>Tanja</strong>: „Einmal für die Übersicht (deine Startseite) und einmal für den einzelnen Beitrag. Manche Themes zeigen das Bild nicht automatisch im Beitrag selbst – dann musst du es explizit aktivieren.&#8220;</p>



<h3 class="wp-block-heading">5.4 Eine einfache Suche installieren</h3>



<p>Basis-Suche aktivieren</p>



<ol class="wp-block-list">
<li>Design → Customizer → Header</li>



<li>Im Header-Builder auf ein &#8222;+&#8220; klicken</li>



<li>Lupe (Suche) auswählen und platzieren</li>



<li>Veröffentlichen</li>
</ol>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440088c401&quot;}" data-wp-interactive="core/image" data-wp-key="69e440088c401" class="wp-block-image aligncenter size-large is-resized wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="776" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/01/BILD-11-Screenshot-Astra-Header-Builder-im-Customizer-–-„-Element-hinzufuegen-und-Auswahl-„Search-Lupe-im-Header-1-1024x776.png" alt="BILD 11 - Screenshot Astra Header-Builder im Customizer – „+“ Element hinzufügen und Auswahl „Search“ Lupe im Header" class="wp-image-354" style="width:800px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/01/BILD-11-Screenshot-Astra-Header-Builder-im-Customizer-–-„-Element-hinzufuegen-und-Auswahl-„Search-Lupe-im-Header-1-1024x776.png 1024w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-11-Screenshot-Astra-Header-Builder-im-Customizer-–-„-Element-hinzufuegen-und-Auswahl-„Search-Lupe-im-Header-1-300x227.png 300w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-11-Screenshot-Astra-Header-Builder-im-Customizer-–-„-Element-hinzufuegen-und-Auswahl-„Search-Lupe-im-Header-1-768x582.png 768w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-11-Screenshot-Astra-Header-Builder-im-Customizer-–-„-Element-hinzufuegen-und-Auswahl-„Search-Lupe-im-Header-1.png 1529w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 11 &#8211; Screenshot Astra Header-Builder im Customizer – „+“ Element hinzufügen und Auswahl „Search“ Lupe im Header</figcaption></figure>



<p>Erweiterte Suche mit Plugin <a href="https://wordpress.org/plugins/" target="_blank" rel="noopener">Relevanssi</a> (Optional)</p>



<ol class="wp-block-list">
<li>Plugin &#8222;Relevanssi – A Better Search&#8220; installieren</li>



<li>Einstellungen → Indexierung → &#8222;Index aufbauen&#8220;</li>



<li>Der Index wird automatisch bei neuen Beiträgen aktualisiert</li>



<li>Suchergebnisse werden nach Relevanz sortiert und Begriffe hervorgehoben</li>
</ol>



<p><strong>Ulf</strong>: „Warum brauche ich Relevanssi? Die Standard-Suche funktioniert doch.&#8220;<br><strong>Tanja</strong>: „Die Standard-WordPress-Suche ist simpel. Sie findet nur exakte Begriffe. Relevanssi durchsucht auch Synonyme, gewichtet Überschriften höher und hebt Suchbegriffe hervor. Für Besucher ist das viel hilfreicher.&#8220;</p>



<h2 class="wp-block-heading">6 Weitere Plugins und Tools einrichten</h2>



<p><strong>Bernd</strong>: „Ich installiere einfach alle Plugins, die gut klingen.&#8220;<br><strong>Tanja</strong>: „Bitte nicht. Jedes Plugin ist zusätzlicher Code, der geladen werden muss. Zu viele Plugins machen deine Seite langsam und unsicher. Die Faustregel lautet: so wenig wie möglich, aber so viele wie nötig.&#8220;</p>



<p>Bei Plugins gilt die Faustregel: so wenig wie möglich, aber so viele wie nötig. Zu viele Plugins können Sicherheit und Performance verschlechtern.</p>



<p>Bereits installierten Plugins:</p>



<ul class="wp-block-list">
<li>Sicherheit:&nbsp;Wordfence Security (Brute-Force-Schutz).</li>



<li>Backup:&nbsp;UpdraftPlus (Speichert Backups direkt in Google Drive).</li>



<li>Spam-Schutz:&nbsp;Antispam Bee (Datenschutzfreundlich, da lokal).</li>



<li>Login-Schutz:&nbsp;WPS Hide Login (ändert die Adminzugangs-URL).</li>
</ul>



<p>Zusätzlich empfehlen ich folgende Plugins:<br><a href="https://wordpress.org/plugins/" target="_blank" rel="noopener">WP Fastest Cache</a></p>



<ul class="wp-block-list">
<li>Verbessert die Ladegeschwindigkeit durch Caching</li>



<li>Installation: Plugin installieren → Aktivieren → WP Fastest Cache → Einstellungen → &#8222;Cache-System&#8220; aktivieren → Submit</li>
</ul>



<p><strong>Ulf</strong>: „Caching? Was macht das?&#8220;<br><strong>Tanja</strong>: „Stell dir vor, du kopierst ein Dokument, statt es jedes Mal neu zu schreiben. Caching speichert eine fertige Version deiner Website und liefert diese aus – statt sie jedes Mal neu zu berechnen. Das macht deine Seite deutlich schneller.&#8220;</p>



<p><a href="https://wordpress.org/plugins/" target="_blank" rel="noopener">Rank Math SEO</a></p>



<p><strong>Ulf</strong>: „SEO? Das ist doch, damit man bei Google gefunden wird, oder?&#8220;<br><strong>Tanja</strong>: „Genau. Rank Math hilft dir, deine Seite für Suchmaschinen zu optimieren – Meta-Daten, Seitenstruktur, SEO-Signale. Alles an einem Ort.&#8220;<br><strong>Bernd</strong>: „Ich nehm einfach den Advanced Mode. Klingt professioneller.&#8220;<br><strong>Tanja</strong>: „Bernd, ausnahmsweise liegst du richtig – Advanced Mode ist am Ende wichtig. Aber du musst die Installation im einfachen Modus machen, sonst fehlen dir später Funktionen. Also:<br>Setup im einfachen Modus, dann auf Advanced umschalten.&#8220;</p>



<ul class="wp-block-list">
<li>Optimiert WordPress-Websites technisch und inhaltlich für Suchmaschinen, indem es Meta-Daten, Seitenstruktur und SEO-Signale zentral steuert.</li>



<li>Installation: Plugin installieren → Aktivieren → Setup-Assistent</li>



<li>Modus &#8222;Einfach&#8220;</li>



<li>Google-Dienste überspringen</li>



<li>Wichtige erste Einstellung: Rank Math SEO -&gt; Dashboard -&gt; oben rechts &#8222;Advanced Mode&#8220;, damit hast Du später im Editor mehr Möglichkeiten Rank Math SEO pro Seite und Beitrag anzupassen.</li>
</ul>



<figure data-wp-context="{&quot;imageId&quot;:&quot;69e440088ce5b&quot;}" data-wp-interactive="core/image" data-wp-key="69e440088ce5b" class="wp-block-image aligncenter size-large is-resized wp-lightbox-container"><img loading="lazy" decoding="async" width="1024" height="711" data-wp-class--hide="state.isContentHidden" data-wp-class--show="state.isContentVisible" data-wp-init="callbacks.setButtonStyles" data-wp-on--click="actions.showLightbox" data-wp-on--load="callbacks.setButtonStyles" data-wp-on-window--resize="callbacks.setButtonStyles" src="https://www.foundic.org/wp-content/uploads/2026/01/BILD-12-Screenshot-WordPress-Backend-Plugins-Uebersicht-1024x711.png" alt="BILD 12 - Screenshot WordPress-Backend - Plugins Übersicht" class="wp-image-358" style="aspect-ratio:1.4402412404077682;width:790px;height:auto" srcset="https://www.foundic.org/wp-content/uploads/2026/01/BILD-12-Screenshot-WordPress-Backend-Plugins-Uebersicht-1024x711.png 1024w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-12-Screenshot-WordPress-Backend-Plugins-Uebersicht-300x208.png 300w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-12-Screenshot-WordPress-Backend-Plugins-Uebersicht-768x533.png 768w, https://www.foundic.org/wp-content/uploads/2026/01/BILD-12-Screenshot-WordPress-Backend-Plugins-Uebersicht.png 1531w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><button
			class="lightbox-trigger"
			type="button"
			aria-haspopup="dialog"
			aria-label="Vergrößern"
			data-wp-init="callbacks.initTriggerButton"
			data-wp-on--click="actions.showLightbox"
			data-wp-style--right="state.imageButtonRight"
			data-wp-style--top="state.imageButtonTop"
		>
			<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
				<path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
			</svg>
		</button><figcaption class="wp-element-caption">BILD 12 &#8211; Screenshot WordPress-Backend &#8211; Plugins Übersicht</figcaption></figure>



<p>Folgende Plugins stehen auf meiner ToDo Liste für später:</p>



<ul class="wp-block-list">
<li>Cookie-Consent-Tool wie Complianz oder Borlabs,&nbsp;bevor ich Google Analytics &amp; AdSense installiere</li>



<li>Inhaltsverzeichnis-Plugin wie Easy Table of Contents</li>



<li>Bildoptimierungs-Plugin wie Shortpixel Optimizer</li>



<li>KI-Plugins wie Jetpack AI&nbsp;oder spezielle SEO-KI-Erweiterungen</li>
</ul>



<p><strong>Bernd</strong>: „KI-Plugins? Schreibt mir die KI dann meine Artikel?&#8220;<br><strong>Tanja</strong>: „Teilweise. KI kann dir helfen, Überschriften zu optimieren, Meta-Beschreibungen zu generieren oder Texte zu überarbeiten. Aber die Verantwortung bleibt bei dir.&#8220;</p>



<h2 class="wp-block-heading">7 Fazit</h2>



<p><strong>Ulf</strong>: „Das war&#8217;s? Meine Website steht?&#8220;<br><strong>Tanja</strong>: „Ja. Du hast jetzt eine voll funktionsfähige WordPress-Website. Mit eigener Domain, eigenem Design, Sicherheitsmaßnahmen und rechtlichen Pflichtseiten.&#8220;<br><strong>Bernd</strong>: „Hätte ich doch gleich Wix genommen.&#8220;<br><strong>Tanja</strong>: „Bernd, du hast jetzt volle Kontrolle. Du kannst Plugins installieren, Themes wechseln, deine Seite migrieren, wann immer du willst. Bei Wix wärst du in einem goldenen Käfig.&#8220;<br><strong>Ulf</strong>: „Ehrlich gesagt dachte ich, das wird viel komplizierter.&#8220;<br><strong>Tanja</strong>: „Genau das ist der Punkt. WordPress wirkt am Anfang einschüchternd, aber wenn du die Grundlagen einmal verstanden hast, läuft alles flüssig. Und das Beste: Du bist nicht abhängig von einem Anbieter.&#8220;</p>



<p>Hast du Fragen zur Installation oder steckst bei einem Schritt fest?&nbsp;Oder hast du Verbesserungsvorschläge für diese Anleitung oder foundic.org? Ich freue mich über dein Feedback in den Kommentaren!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.foundic.org/de/eigene-website-mit-wordpress-fuer-anfaenger/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
