| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .forgejo/workflows | ||
| .idea | ||
| .env | ||
| .gitignore | ||
| AGENTS.md | ||
| CICD-Actions.md | ||
| CLAUDE.md | ||
| docker-compose.yml | ||
| LICENSE | ||
| Projekt.md | ||
| README.md | ||
imagor – Bildauslieferung für die KI-Bildkennzeichnung
imagor liefert Produktbilder für den Shopware-6-Shop aus und versieht dabei KI-generierte bzw.
-veränderte Bilder mit einem sichtbaren deutschen Text-Wasserzeichen (Art. 50 Abs. 4 KI-VO).
Das Plugin WSC_SWPlugin_AiSeoTools (ImagorUrlBuilder) baut die URLs, die hier ankommen.
Template-Hinweis: Konfiguration läuft über die
.env. Vor dem Einsatz ALLECHANGE_ME-Platzhalter ersetzen (HOSTRULE,HTTP_LOADER_ALLOWED_SOURCES,IMAGOR_SECRET).
Voraussetzungen
- Docker & Docker Compose v2
- Traefik-Stack (
docker-traefik-proxy) läuft bereits und stellt das externe Netzwerktraefik_proxy_networkbereit - Der Shop (
projekt-sw6) ist öffentlich per HTTPS erreichbar (imagor holt Quellbilder per HTTP, kein Shared-Volume nötig)
Verzeichnisstruktur
docker-imagor-media/
├── .env ← Konfiguration (Domain, Allowlist, Image-Tag)
├── docker-compose.yml ← imagor Stack-Datei
└── README.md
Stack starten
docker compose up -d
Konfiguration
Alle Einstellungen werden über die .env gesetzt und in der docker-compose.yml als
${VARIABLE} referenziert.
| Variable (.env) | Default/Platzhalter | Beschreibung |
|---|---|---|
IMAGOR_IMAGE_TAG |
1.9.3 |
Gepinnte Image-Version (letzte benannte Release) |
HOSTRULE |
Host(\img.CHANGE_ME....`)` |
Traefik-Routing-Regel, echte Subdomain eintragen |
PROXY_NETWORK |
traefik_proxy_network |
Name des externen Traefik-Netzwerks |
HTTP_LOADER_ALLOWED_SOURCES |
CHANGE_ME.example.com |
Erlaubte Quell-Hosts für Bilder (glob, csv) — sicherheitsrelevant (SSRF) |
IMAGOR_LOAD_TIMEOUT |
30s |
Timeout beim Laden von Quellbildern |
RESULT_STORAGE_EXPIRATION |
168h |
Wie lange gecachte Bild-Varianten aufbewahrt werden |
IMAGOR_SECRET |
CHANGE_ME |
Aktuell unbenutzt (siehe "Bekannte Einschränkung" unten) |
Sicherheit: HTTP-Loader-Allowlist & SSRF-Schutz
imagor holt Quellbilder per HTTP nach HTTP_LOADER_ALLOWED_SOURCES — ohne Einschränkung wäre
imagor ein offener URL-Proxy (SSRF-Risiko). Der Stack setzt deshalb zusätzlich:
HTTP_LOADER_BLOCK_LOOPBACK_NETWORKS=1(blockiert127.0.0.1/::1)HTTP_LOADER_BLOCK_PRIVATE_NETWORKS=1(blockiert10.x.x.x,192.168.x.x, …)HTTP_LOADER_BLOCK_LINK_LOCAL_NETWORKS=1(blockiert169.254.x.x)
HTTP_LOADER_ALLOWED_SOURCES muss vor dem produktiven Einsatz auf die echte(n)
Shop-Domain(s) gesetzt werden — nicht auf * oder leer lassen.
Bekannte Einschränkung: Unsafe-Modus
IMAGOR_UNSAFE=1 ist aktuell aktiv, weil ImagorUrlBuilder im Plugin
WSC_SWPlugin_AiSeoTools noch keine signierten URLs baut (dort im Code als bewusste,
dokumentierte Vereinfachung markiert). Das bedeutet: jeder, der die Bild-Pfad-Struktur kennt,
kann beliebige Transformationen der erlaubten Quellbilder anfordern (kein Zugriff auf fremde
Daten, aber zusätzliche Rechenlast wäre theoretisch erzwingbar).
Nicht im Alleingang auf signierte URLs (IMAGOR_SECRET) umstellen — das würde alle
Anfragen des Plugins sofort brechen. Eine Umstellung ist eine koordinierte Änderung in
beiden Repos (hier: IMAGOR_UNSAFE entfernen + echten IMAGOR_SECRET setzen; im Plugin:
ImagorUrlBuilder um HMAC-Signierung erweitern).
Nützliche Befehle
# Stack starten
docker compose up -d
# Stack stoppen
docker compose down
# Logs verfolgen
docker logs -f imagor
# Beispiel-Request gegen eine erlaubte Quelle (unsafe-Modus)
curl -I "https://img.example.com/unsafe/400x400/shop.example.com/media/xy/bild.jpg"
Troubleshooting
403/Fehler beim Laden von Quellbildern:
- Prüfen ob die Domain in
HTTP_LOADER_ALLOWED_SOURCESeingetragen ist - Prüfen ob die Quell-URL wirklich per HTTPS öffentlich erreichbar ist
Traefik liefert 404 für die imagor-Domain:
HOSTRULEin der.envprüfen (echte Domain stattCHANGE_ME)- Prüfen ob
docker-traefik-proxyläuft undtraefik_proxy_networkexistiert:docker network ls | grep traefik_proxy_network
Ergebnis-Bilder wirken nicht aktualisiert:
- Gecachte Result-Storage-Variante ist noch nicht abgelaufen (
RESULT_STORAGE_EXPIRATION) — Cache-Ordner liegt unter./volumes/result
CI/CD
Die Pipeline (.forgejo/workflows/ci.yml) läuft self-hosted auf Forgejo, ganz ohne externe Actions (Checkout per git clone). Anders als bei den Nachbar-Stacks gibt es hier keinen Code-Mirror nach Codeberg:
validate(jeder Push/PR aufmain+ Tags):docker compose config -q,yamllint(relaxed) undgitleaks(nur Working-Tree). Es wird docker compose v2 genutzt (Runner-Imagecatthehacker/ubuntu:act-latest; nötig u. a. für v2-Keys wiedockerfile_inline), apt nur als Fallback – kein 64-MB-github-Download.release(nur Tagv*): baut ein schlankes Deploy-ZIP und hängt es an ein Forgejo-Release und – als Backup – an ein Codeberg-Release (die Releases-Unit am Codeberg-Repo wird dabei automatisch aktiviert).
Release auslösen:
git tag v1.1
git push origin v1.1
Details siehe CICD-Actions.md.
Lizenz
Copyright (C) 2026 Christian Säum – web-seo-consulting.eu
Dieses Projekt steht unter der GNU Affero General Public License, Version 3
oder (nach deiner Wahl) einer späteren Version (AGPL-3.0-or-later). Der
vollständige Lizenztext steht in der Datei LICENSE.
Du darfst die Software nutzen, weitergeben und – auch kommerziell – verkaufen.
Gibst du eine veränderte Fassung weiter oder betreibst du sie über ein
Netzwerk (z. B. als Dienst), muss deren vollständiger Quellcode ebenfalls
unter der AGPL-3.0-or-later verfügbar sein. Der Copyright-Hinweis und die
Nennung des ursprünglichen Autors dürfen nicht entfernt werden.
Diese Angabe betrifft nur die in diesem Repository enthaltenen eigenen Dateien (Konfiguration, Skripte, Anpassungen). Eingebundene Fremdsoftware und Container-Images unterliegen weiterhin ihren eigenen Lizenzen.