Öffentliche Anleitung
Steuerdateien im Download-Verzeichnis
Steuerdateien und Download-Struktur
Der DownloadBroker benötigt keine Datenbank. Die Verzeichnisstruktur, Dateinamen und wenigen Steuerdateien bestimmen vollständig, was angezeigt und wer darauf zugreifen darf.
Verbindliche Verzeichnisstruktur
downloads/
├── logo.svg (optional; Name über Branding:LogoFileName)
├── info.md
├── access.json
└── flowwer-agent/
├── info.md
├── access.json
└── 2025.5.669/
├── info.md
├── info.windows.md
├── Flowwer_Agent__m25-5-669.zip
├── Flowwer_Agent__m25-5-669.zip.info.md
└── Flowwer_Agent__m25-5-669.zip.access.json
Die erste Ebene ist das Artefakt, die zweite Ebene eine semantische Version wie 2.5.0,
2.5.0-beta.1 oder 3.0.0-rc.2.
Download-Dateien und optionale Plattformangaben
Der Dateiname eines Downloads ist frei. Artefakt und Version ergeben sich bereits aus den beiden Verzeichnisebenen und müssen im Dateinamen nicht wiederholt werden. Damit sind beispielsweise alle folgenden Namen gültig:
Flowwer_Agent__m25-5-669.zip
LogoPackage_2026.01_any.zip
DNF-GmbH_Briefpapier.dot
DotNetFabrik Basic Wordvorlage.docx
Eine Datei wird angeboten, wenn sie:
- direkt in einem gültigen Versionsverzeichnis liegt,
- keine Steuerdatei ist,
- nicht mit einem Punkt beginnt und
- eine unter
Catalog:AllowedExtfreigegebene Dateiendung besitzt.
Optionale Gruppierung nach Betriebssystem und Architektur
Plattformangaben können am Ende des Dateinamens ergänzt werden. Sie dienen ausschließlich der übersichtlichen Gruppierung in der Oberfläche und sind keine Voraussetzung für einen Download:
<beliebiger-name>_<os>_<arch>.<extension>
<beliebiger-name>_<os>.<extension>
Zulässige Betriebssysteme:
any
windows
linux
macos
Zulässige Architekturen:
any
x64
x86
arm64
Beispiele:
FLOWWER-Agent_windows_x64.zip
FLOWWER-Agent_linux_arm64.tar.gz
FLOWWER-Agent_macos.zip
LogoPackage_2026.01_any.zip
Die Plattformschlüssel werden ohne Beachtung der Groß-/Kleinschreibung erkannt. Fehlt ein bekannter Endsuffix, bleibt die Datei ein normaler Download und wird ohne Plattformüberschrift angezeigt. Unbekannte Plattformschlüssel werden nicht interpretiert und sperren die Datei nicht.
Informationsdateien
Alle Beschreibungen werden als Markdown gespeichert. Eingebettetes Raw-HTML wird nicht gerendert. Es gibt ausschließlich diese Namen:
| Geltungsbereich | Dateiname | Beispiel |
|---|---|---|
| Gesamter Katalog | info.md im Root |
downloads/info.md |
| Artefakt | info.md im Artefaktverzeichnis |
flowwer-agent/info.md |
| Version | info.md im Versionsverzeichnis |
2.5.0/info.md |
| Betriebssystem | info.<os>.md |
info.windows.md |
| Einzelne Datei | <vollständiger-dateiname>.info.md |
setup.zip.info.md |
Andere Markdown-, Text- oder HTML-Dateien sind keine Steuerdateien. Sie werden wie normale
Downloadkandidaten behandelt und nur angeboten, wenn ihre Endung in Catalog:AllowedExt steht.
Versionsdarstellung im Downloadbereich steuern
Standardmäßig zeigt DownloadBroker oberhalb der aktuellen Downloadliste „Downloads für Version …“.
Ein Versionsstand wird nur ergänzt, wenn er in der info.md des aktuell sichtbaren
Versionsverzeichnisses explizit mit UpdatedAtUtc gepflegt wurde. Dieses Standardverhalten heißt
Auto.
Die info.md im Artefaktverzeichnis kann die Darstellung über VersionDisplay ändern:
---
VersionDisplay: VersionOnly
---
# FLOWWER Logo-Paket
| Wert | Darstellung |
|---|---|
Auto |
Zeigt die Version und – sofern explizit vorhanden – den Versionsstand. Dies ist der Standard. |
VersionOnly |
Zeigt ausschließlich die Version, auch wenn UpdatedAtUtc gepflegt ist. |
Hidden |
Blendet die Version aus; der Abschnitt heißt nur noch „Downloads“. |
Die Werte werden ohne Beachtung der Groß-/Kleinschreibung gelesen. Ein leerer oder unbekannter Wert
führt zu einer Warning und verwendet anschließend Auto. VersionDisplay beeinflusst ausschließlich
die Darstellung. Die Ermittlung der neuesten Version, Downloadpfade und Gruppierung früherer
Versionen bleiben unverändert.
Versionsstand explizit festlegen
Ein angezeigter Versionsstand besitzt immer eine fachlich bewusst gepflegte Quelle. DownloadBroker verwendet dafür nicht mehr den vom Storage gelieferten Änderungszeitpunkt des Versionsverzeichnisses. Verzeichniszeitstempel können sich bereits durch Kopieren, Wiederherstellen oder Ergänzen einer Steuerdatei ändern und sind deshalb kein verlässlicher Versionsstand.
Die info.md im Versionsverzeichnis kann optional YAML-Frontmatter mit UpdatedAtUtc enthalten:
---
UpdatedAtUtc: 2024-11-18T13:42:00Z
---
## Änderungen
- Fehler beim Import behoben
UpdatedAtUtc muss ein ISO-8601-Zeitstempel mit Z oder einem expliziten Offset sein. Ein Offset
wird intern nach UTC normalisiert. Das Frontmatter wird nicht als Bestandteil des Markdown-Inhalts
angezeigt. Fehlt UpdatedAtUtc oder ist der Wert ungültig beziehungsweise mehrfach angegeben, bleibt
der Versionsstand leer; bei ungültigen Metadaten protokolliert DownloadBroker zusätzlich eine
Warning. Es gibt keinen Rückfall auf das Datum des Versionsverzeichnisses.
Metadaten werden bei allen info.md-Dateien einheitlich gelesen, aber nur in ihrem definierten
Geltungsbereich verwendet: VersionDisplay gilt aus der Artefakt-info.md, UpdatedAtUtc aus der
info.md des aktuell sichtbaren Versionsverzeichnisses.
Das Dateidatum direkt an einer konkreten Download-Datei bleibt davon unabhängig. Es stammt
weiterhin aus LastWriteUtc dieser Datei und bezeichnet den Storage-Zeitstempel genau dieses
Downloads, nicht den Versionsstand des Artefakts.
Zugriffsregeln
Alle Zugriffsregeln stehen in access.json. Es gibt keine Markerdateien und keine Passwörter in
Dateinamen oder URLs.
Mögliche Ablageorte, von spezifisch nach allgemein:
<vollständiger-dateiname>.access.jsonaccess.jsonim Versionsverzeichnisaccess.jsonim Artefaktverzeichnisaccess.jsonim Katalog-Root
Die spezifischste vorhandene Regel ersetzt die allgemeinere Regel vollständig. Eigenschaften werden nicht aus mehreren Dateien zusammengemischt.
Ohne passende access.json ist ein Download öffentlich.
Nur internes Netzwerk
{
"internal": true,
"hint": "Nur für Mitarbeitende"
}
Zugangscode, unabhängig vom Netzwerk
{
"credentialId": "kunde-acme",
"hint": "Zugang für ACME GmbH"
}
Die eigentlichen Codes stehen in der Anwendungskonfiguration. access.json enthält nur die
credentialId.
Intern oder mit Zugangscode
{
"internal": true,
"credentialId": "kunde-acme",
"mode": "any",
"hint": "Intern frei, extern mit Zugangscode"
}
Bei zwei Bedingungen ist any der Standard und kann weggelassen werden. Zugriff ist dann möglich,
wenn mindestens eine Bedingung erfüllt ist.
Intern und mit Zugangscode
{
"internal": true,
"credentialId": "wartung",
"mode": "all",
"hint": "Nur intern mit zusätzlichem Wartungscode"
}
all verlangt alle angegebenen Bedingungen gleichzeitig.
Gültige Eigenschaften
| Eigenschaft | Typ | Bedeutung |
|---|---|---|
internal |
Boolean | Zugriff aus einem unter AccessControl:InternalNetworks definierten Netz |
credentialId |
String | Verweis auf einen konfigurierten Zugangscode |
mode |
any oder all |
Verknüpfung mehrerer Bedingungen |
hint |
String | Kurzer Hinweis in der Oberfläche |
Eigenschaftsnamen sowie die Werte any und all müssen exakt in der dokumentierten
Kleinschreibung verwendet werden. Unbekannte Eigenschaften, ungültige Werte oder fehlerhaftes JSON
führen zu einer gesperrten Regel. Damit kann ein Tippfehler den Zugriff nicht versehentlich öffnen.
Zugangscodes konfigurieren
{
"DownloadCredentials": {
"Enabled": true,
"HeaderName": "X-DownloadBroker-Key",
"CookieName": "downloadbroker-download-credentials",
"CookieLifetimeHours": 8,
"Credentials": {
"kunde-acme": {
"Secret": "ein-langes-zufaelliges-geheimnis"
}
}
}
}
Der Schlüssel unter Credentials ist zugleich die credentialId, die in der jeweiligen
.access.json-Datei referenziert wird. Eine separate Id-Eigenschaft gibt es nicht.
Für Produktion kann statt Secret ein Base64-kodierter SHA-256-Hash verwendet werden:
{
"DownloadCredentials": {
"Credentials": {
"kunde-acme": {
"SecretSha256Base64": "..."
}
}
}
}
Browser übermitteln einen Code per Formular. Nach erfolgreicher Prüfung speichert der Server nur die freigeschaltete Credential-ID in einem verschlüsselten HTTP-only Cookie. Automatisierte Clients können den konfigurierten Header verwenden. Zugangscodes in Query-Strings werden nicht unterstützt.
Sichtbarkeit nicht berechtigter Dateien
{
"Catalog": {
"HideUnauthorizedDownloads": true
}
}
false: Die Datei bleibt sichtbar und zeigt ihren aktuellen Zugriffsstatus.true: Die Datei erscheint erst, wenn der Besucher sie tatsächlich herunterladen darf.
Der Download-Endpunkt prüft die Berechtigung immer selbstständig; die Sichtbarkeit ist keine Sicherheitsgrenze.
Branding
{
"Branding": {
"HeaderText": "FLOWWER Downloads",
"FooterText": "DotNetFabrik GmbH",
"HeaderBackgroundColor": "#172B4D",
"HeaderForegroundColor": "#FFFFFF",
"FooterBackgroundColor": "#172B4D",
"FooterForegroundColor": "#FFFFFF",
"LogoFileName": "logo.svg",
"LogoMaxWidthPixels": 180,
"LogoMaxHeightPixels": 40
}
}
HeaderText steuert Kopfzeile und Browser-Titel. Ein leerer HeaderText blendet den Text im
Header aus und lässt den Browser-Titel ohne Branding-Suffix. Ein leerer FooterText blendet den
linken Footertext aus.
HeaderBackgroundColor, HeaderForegroundColor, FooterBackgroundColor und
FooterForegroundColor steuern die Farben der beiden Bereiche. Die Angaben sind optional und
werden ausschließlich im Format #RRGGBB akzeptiert. Ohne Wert gelten die Bootstrap-Standardfarben.
Die Environment-Kennzeichnung beeinflusst Header und Seitenhintergrund nicht; Development und Staging
werden ausschließlich über den farbigen Streifen oberhalb des Headers markiert.
LogoFileName verweist auf eine optionale Logo-Datei direkt im Storage-Root. Es gibt keine
zusätzliche Branding-Steuerdatei und keine Suchkonvention über mehrere Dateinamen. Ohne Wert wird
kein Logo angefordert. Unterstützt werden ausschließlich svg, png, webp, jpg und jpeg.
Der Dateiname darf keinen Verzeichnispfad enthalten.
Das Logo ist ein öffentliches Portal-Asset und unter /branding/logo erreichbar; Zugriffsregeln aus
access.json gelten dafür nicht. Die Datei darf höchstens 2 MiB groß sein. Inhalt und auch ein
fehlendes Logo werden fünf Minuten im Arbeitsspeicher gecacht. Browser erhalten zusätzlich ETag-,
Last-Modified- und Cache-Control-Header.
LogoMaxWidthPixels und LogoMaxHeightPixels begrenzen den Darstellungsrahmen im Header, ohne die
Bilddatei selbst zu verändern. Zulässig sind 16 bis 600 Pixel Breite und 16 bis 160 Pixel Höhe.
Fehlt die konfigurierte Datei oder kann sie nicht geladen werden, bleibt der Headertext sichtbar und
das fehlerhafte Bild wird aus der Oberfläche entfernt.
Im mitgelieferten Docker Compose können die Werte kompakt über folgende Variablen gesetzt werden:
DOWNLOADBROKER_HEADER=FLOWWER Downloads
DOWNLOADBROKER_FOOTER=DotNetFabrik GmbH
DOWNLOADBROKER_HEADER_BACKGROUND_COLOR="#172B4D"
DOWNLOADBROKER_HEADER_FOREGROUND_COLOR="#FFFFFF"
DOWNLOADBROKER_FOOTER_BACKGROUND_COLOR="#172B4D"
DOWNLOADBROKER_FOOTER_FOREGROUND_COLOR="#FFFFFF"
DOWNLOADBROKER_LOGO_FILE=logo.svg
DOWNLOADBROKER_LOGO_MAX_WIDTH=180
DOWNLOADBROKER_LOGO_MAX_HEIGHT=40
DOWNLOADBROKER_HEADER= beziehungsweise DOWNLOADBROKER_FOOTER= blendet den jeweiligen Text
explizit aus. Der Compose-Default greift nur, wenn die Variable gar nicht gesetzt ist.
Storage
Zulässige Provider sind ausschließlich:
FileSystem
SynologyDsm
Beispiel für ein lokales oder eingebundenes Verzeichnis:
{
"Storage": {
"Provider": "FileSystem"
},
"FileSystem": {
"RootPath": "/data"
}
}
Für Synology DSM werden API Discovery und die von DSM gemeldeten File-Station-Endpunkte verwendet. Fehlt eine benötigte API, bricht der Provider mit einer eindeutigen Meldung ab, statt einen alten Endpunkt zu erraten.
Interne Client-Erkennung diagnostizieren
Beim Start protokolliert die Anwendung auf Information-Level die wirksame Netzwerkkonfiguration:
- unter
AccessControl:InternalNetworkskonfigurierte interne Netze, - Aktivierung und
ForwardLimitder Forwarded Headers, - vertrauenswürdige Proxy-Adressen und Proxy-Netze.
Ohne AccessControl:InternalNetworks gelten ausschließlich Loopback-Adressen als intern. Eine
typische direkte LAN-Konfiguration ist beispielsweise:
AccessControl__InternalNetworks__0=192.168.20.0/24
Jeder HTTP-Request erzeugt zusätzlich einen Information-Logeintrag mit folgenden Werten:
| Wert | Bedeutung |
|---|---|
ConnectionIp |
Direkter TCP-Kommunikationspartner vor der Forwarded-Headers-Auswertung |
ClientIp |
Von der Anwendung tatsächlich für Zugriffsprüfung und Rate Limiting verwendete Adresse |
XForwardedFor |
Unveränderter eingehender X-Forwarded-For-Header oder (none) |
ForwardedForApplied |
Ob der Header die wirksame ClientIp verändert hat |
ActuallyInternal |
Ob die Client-IP zu Loopback oder einem internen Netz gehört |
Internal |
Wirksames Ergebnis nach Berücksichtigung der externen Testansicht |
ExternalSimulation |
Ob Query-Parameter oder Cookie die externe Testansicht erzwingen |
InternalMatch |
Getroffenes CIDR-Netz, loopback oder (none) |
Typische Fehlerbilder lassen sich damit direkt unterscheiden:
InternalMatch=(none): Das tatsächliche Client-Netz fehlt inInternalNetworks.XForwardedForist gesetzt, aberForwardedForApplied=false: Forwarded Headers sind deaktiviert oder der direkte Proxy ist nicht als vertrauenswürdig konfiguriert.ActuallyInternal=true, aberInternal=false: Die externe Testansicht ist aktiv. Sie kann über?networkView=autobeziehungsweise den entsprechenden Schalter in der Oberfläche beendet werden.XForwardedFor=(none)undConnectionIpist eine Docker-/Proxy-Adresse: Die vorgelagerte Komponente reicht die ursprüngliche Client-IP nicht weiter.
Hinter einem Reverse Proxy müssen Forwarded Headers aktiviert und ausschließlich der tatsächliche Proxy beziehungsweise sein dediziertes Netz als vertrauenswürdig eingetragen werden:
ForwardedHeaders__Enabled=true
ForwardedHeaders__KnownProxies__0=172.20.0.5
AccessControl__InternalNetworks__0=192.168.20.0/24
Bei dynamischen Proxy-Adressen kann stattdessen das eng begrenzte Docker-Netz unter
ForwardedHeaders__KnownNetworks eingetragen werden. Das Proxy-Netz gehört nicht in
AccessControl__InternalNetworks, da sonst jeder über diesen Proxy kommende Request als intern
erscheinen könnte, wenn die ursprüngliche Client-IP nicht ausgewertet wird.
Docker-Umgebungsvariablen
ASP.NET-Core-Konfigurationsschlüssel werden in Docker mit doppeltem Unterstrich geschrieben, zum Beispiel:
Branding__HeaderText
Branding__FooterText
Branding__HeaderBackgroundColor
Branding__HeaderForegroundColor
Branding__FooterBackgroundColor
Branding__FooterForegroundColor
Branding__LogoFileName
Catalog__HideUnauthorizedDownloads
Storage__Provider
FileSystem__RootPath
DownloadCredentials__HeaderName
Listenwerte verwenden weiterhin einen Index. Credentials werden dagegen über ihre ID als Dictionary-Schlüssel benannt:
AccessControl__InternalNetworks__0=10.0.0.0/8
DownloadCredentials__Credentials__kunde-acme__Secret=...
DownloadCredentials__Credentials__wartung__SecretSha256Base64=...