Öffentliche Anleitung

Steuerdateien im Download-Verzeichnis

Zur Startseite

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:AllowedExt freigegebene 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:

  1. <vollständiger-dateiname>.access.json
  2. access.json im Versionsverzeichnis
  3. access.json im Artefaktverzeichnis
  4. access.json im 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:InternalNetworks konfigurierte interne Netze,
  • Aktivierung und ForwardLimit der 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 in InternalNetworks.
  • XForwardedFor ist gesetzt, aber ForwardedForApplied=false: Forwarded Headers sind deaktiviert oder der direkte Proxy ist nicht als vertrauenswürdig konfiguriert.
  • ActuallyInternal=true, aber Internal=false: Die externe Testansicht ist aktiv. Sie kann über ?networkView=auto beziehungsweise den entsprechenden Schalter in der Oberfläche beendet werden.
  • XForwardedFor=(none) und ConnectionIp ist 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=...