[{"data":1,"prerenderedAt":1988},["ShallowReactive",2],{"doc-\u002Fde\u002Fusers":3,"docnav-de":179},{"id":4,"title":5,"body":6,"description":170,"extension":171,"meta":172,"nav":173,"navigation":174,"path":175,"seo":176,"stem":177,"__hash__":178},"docs\u002Fde\u002Fusers.md","Benutzer & Rollen",{"type":7,"value":8,"toc":161},"minimark",[9,14,18,22,125,128,131,134,138,141,145,148],[10,11,13],"h2",{"id":12},"erster-start","Erster Start",[15,16,17],"p",{},"Beim ersten Öffnen des Origin legt der Setup-Bildschirm das erste Admin-Konto an. Die Anmeldung\ndanach erfolgt über ein lokales Konto mit Session-Cookie.",[10,19,21],{"id":20},"rollen","Rollen",[23,24,25,43],"table",{},[26,27,28],"thead",{},[29,30,31,34,37,40],"tr",{},[32,33],"th",{},[32,35,36],{},"Viewer",[32,38,39],{},"Reviewer",[32,41,42],{},"Admin",[44,45,46,59,70,81,92,103,114],"tbody",{},[29,47,48,52,55,57],{},[49,50,51],"td",{},"Katalog lesen",[49,53,54],{},"✓",[49,56,54],{},[49,58,54],{},[29,60,61,64,66,68],{},[49,62,63],{},"Pakete anlegen & bearbeiten",[49,65],{},[49,67,54],{},[49,69,54],{},[29,71,72,75,77,79],{},[49,73,74],{},"Versionen freigeben",[49,76],{},[49,78,54],{},[49,80,54],{},[29,82,83,86,88,90],{},[49,84,85],{},"Sites verwalten",[49,87],{},[49,89,54],{},[49,91,54],{},[29,93,94,97,99,101],{},[49,95,96],{},"Benutzer verwalten",[49,98],{},[49,100],{},[49,102,54],{},[29,104,105,108,110,112],{},[49,106,107],{},"Edge-Nodes verwalten",[49,109],{},[49,111],{},[49,113,54],{},[29,115,116,119,121,123],{},[49,117,118],{},"Lizenz verwalten",[49,120],{},[49,122],{},[49,124,54],{},[15,126,127],{},"Rollen werden serverseitig durchgesetzt, nicht nur in der Oberfläche abgebildet — die Session eines\nViewers kann eine Reviewer-Aktion auch bei direktem API-Aufruf nicht ausführen.",[10,129,96],{"id":130},"benutzer-verwalten",[15,132,133],{},"Admin → Benutzer: Konto anlegen, Rolle ändern oder entfernen.",[10,135,137],{"id":136},"audit-log","Audit-Log",[15,139,140],{},"Jede Freigabe und jede administrative Aktion wird in einem nur anfügbaren Audit-Log erfasst — wer\nwas wann getan hat. Typische Einträge: eine Version freigegeben oder auf Upstream zurückgesetzt,\nein Site-Token angelegt oder widerrufen, ein Node enrollt oder widerrufen, die Rolle eines\nBenutzers geändert, ein Lizenz-Token ersetzt. Jeder angemeldete Benutzer kann es lesen; was\nprotokolliert wird, ist nicht konfigurierbar.",[10,142,144],{"id":143},"sso-und-mfa","SSO und MFA",[15,146,147],{},"Die Anwendung liefert lokale Konten aus.",[149,150,152],"edition-callout",{"edition":151},"enterprise",[15,153,154,155,160],{},"Single Sign-on (OIDC\u002FSAML) und Mehr-Faktor-Authentifizierung (TOTP) werden über lizenzierte Plugins\nbereitgestellt, die die Anwendung lädt, sobald Ihre Lizenz die passende Berechtigung trägt. Siehe\n",[156,157,159],"a",{"href":158},"\u002Fde\u002Fdocs\u002Feditions-licensing","Editionen & Lizenzierung",".",{"title":162,"searchDepth":163,"depth":163,"links":164},"",2,[165,166,167,168,169],{"id":12,"depth":163,"text":13},{"id":20,"depth":163,"text":21},{"id":130,"depth":163,"text":96},{"id":136,"depth":163,"text":137},{"id":143,"depth":163,"text":144},"Konten, Rollen, das Audit-Log und wie SSO\u002FMFA sich einfügen.","md",{},50,true,"\u002Fde\u002Fusers",{"title":5,"description":170},"de\u002Fusers","Ne0UTwRY08MHu_g05Rlx7ZOE9AjEOxWa86aZ7wZOESQ",[180,464,623,780,1022,1146,1275,1701,1804],{"id":181,"title":182,"body":183,"description":457,"extension":171,"meta":458,"nav":459,"navigation":174,"path":460,"seo":461,"stem":462,"__hash__":463},"docs\u002Fde\u002Fgetting-started.md","Erste Schritte",{"type":7,"value":184,"toc":448},[185,189,206,210,216,220,227,310,317,321,328,332,335,352,363,367,374,396,399,403,444],[10,186,188],{"id":187},"was-ist-kvellman","Was ist kvellman?",[15,190,191,192,196,197,200,201,205],{},"kvellman ist ein selbst gehostetes, ",[193,194,195],"strong",{},"winget-kompatibles"," Paket-Repository. Sie tragen es als\nzusätzliche winget-Quelle ein — die winget-CLI fragt es exakt so ab wie die offizielle\nMicrosoft-Quelle. Der ",[193,198,199],{},"Origin"," ist der Server, den Sie betreiben: die Admin-Oberfläche, die\nwinget-Source-API und die Installer-Auslieferung. Clients sind unveränderte ",[202,203,204],"code",{},"winget","-Installationen\n— auf der Windows-Seite installiert sich nichts außer der Quellenregistrierung.",[10,207,209],{"id":208},"was-sie-brauchen","Was Sie brauchen",[15,211,212,213,160],{},"Einen Host, der einen Container ausführen kann, einen darauf zeigenden DNS-Namen und\nvertrauenswürdiges HTTPS. winget verweigert REST-Quellen, die nicht über HTTPS mit einem\nvertrauenswürdigen Zertifikat laufen — bei neueren winget-Versionen auch für ",[202,214,215],{},"localhost",[10,217,219],{"id":218},"_1-origin-starten-docker","1. Origin starten (Docker)",[15,221,222,223,226],{},"Die Community-Edition läuft aus einem einzelnen ",[202,224,225],{},"docker compose","-Stack (App + PostgreSQL). Mit\neiner auf Ihren Host zeigenden Domain und offenen Ports 80\u002F443:",[228,229,233],"pre",{"className":230,"code":231,"language":232,"meta":162,"style":162},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","git clone \u003Copen-core-repo> kvellman && cd kvellman\ncp .env.deploy.example .env.deploy   # DOMAIN, NUXT_SESSION_PASSWORD, POSTGRES_PASSWORD setzen\ndocker compose --env-file .env.deploy up -d\n","bash",[202,234,235,275,290],{"__ignoreMap":162},[236,237,240,244,248,252,255,259,262,265,268,272],"span",{"class":238,"line":239},"line",1,[236,241,243],{"class":242},"sBMFI","git",[236,245,247],{"class":246},"sfazB"," clone",[236,249,251],{"class":250},"sMK4o"," \u003C",[236,253,254],{"class":246},"open-core-rep",[236,256,258],{"class":257},"sTEyZ","o",[236,260,261],{"class":250},">",[236,263,264],{"class":246}," kvellman",[236,266,267],{"class":250}," &&",[236,269,271],{"class":270},"s2Zo4"," cd",[236,273,274],{"class":246}," kvellman\n",[236,276,277,280,283,286],{"class":238,"line":163},[236,278,279],{"class":242},"cp",[236,281,282],{"class":246}," .env.deploy.example",[236,284,285],{"class":246}," .env.deploy",[236,287,289],{"class":288},"sHwdD","   # DOMAIN, NUXT_SESSION_PASSWORD, POSTGRES_PASSWORD setzen\n",[236,291,293,296,299,302,304,307],{"class":238,"line":292},3,[236,294,295],{"class":242},"docker",[236,297,298],{"class":246}," compose",[236,300,301],{"class":246}," --env-file",[236,303,285],{"class":246},[236,305,306],{"class":246}," up",[236,308,309],{"class":246}," -d\n",[15,311,312,313,316],{},"Datenbank-Migrationen laufen beim Start automatisch. Öffnen Sie ",[202,314,315],{},"https:\u002F\u002Fihre-domain"," — beim ersten\nAufruf wird das Admin-Konto angelegt.",[10,318,320],{"id":319},"_2-site-token-anlegen","2. Site-Token anlegen",[15,322,323,324,160],{},"In der Weboberfläche: Admin → Site-Tokens → einen anlegen. Der Token wird Teil der URL, über die\nClients diese Quelle erreichen. Was ein Site-Token wirklich steuert, steht unter\n",[156,325,327],{"href":326},"\u002Fde\u002Fdocs\u002Fsites","Sites",[10,329,331],{"id":330},"_3-ein-paket-hinzufügen","3. Ein Paket hinzufügen",[15,333,334],{},"Zwei Wege, ein Paket in den Katalog zu bringen:",[336,337,338,346],"ul",{},[339,340,341,342,345],"li",{},"Aus dem ",[193,343,344],{},"Upstream-Katalog importieren"," (Pakete → Import), oder",[339,347,348,351],{},[193,349,350],{},"Selbst anlegen",": Paket erstellen und ein Manifest hochladen.",[15,353,354,355,358,359,362],{},"In beiden Fällen ist eine neue Version für Clients erst sichtbar, wenn sie ",[193,356,357],{},"freigegeben"," ist —\nöffnen Sie die Version und geben Sie sie frei (Pakete → Ihr Paket → die wartende Version). Das ist\nder Schritt, der am häufigsten übersehen wird: Ein importiertes Paket, das im Dashboard auftaucht,\naber bei ",[202,360,361],{},"winget search"," nichts liefert, braucht fast immer nur die Freigabe.",[10,364,366],{"id":365},"_4-quelle-auf-einem-client-eintragen","4. Quelle auf einem Client eintragen",[15,368,369,370,373],{},"winget verlangt ",[193,371,372],{},"HTTPS"," für eine REST-Quelle. Auf einem Windows-Client (PowerShell):",[228,375,379],{"className":376,"code":377,"language":378,"meta":162,"style":162},"language-powershell shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","winget source add --name kvellman --type Microsoft.Rest --arg \"https:\u002F\u002Fihre-domain\u002Fapi\u002F\u003Csite-token>\"\nwinget search --source kvellman \u003Cbegriff>\nwinget install --source kvellman \u003CPaket.Kennung>\n","powershell",[202,380,381,386,391],{"__ignoreMap":162},[236,382,383],{"class":238,"line":239},[236,384,385],{},"winget source add --name kvellman --type Microsoft.Rest --arg \"https:\u002F\u002Fihre-domain\u002Fapi\u002F\u003Csite-token>\"\n",[236,387,388],{"class":238,"line":163},[236,389,390],{},"winget search --source kvellman \u003Cbegriff>\n",[236,392,393],{"class":238,"line":292},[236,394,395],{},"winget install --source kvellman \u003CPaket.Kennung>\n",[15,397,398],{},"Das war's — Clients installieren interne Software jetzt über Ihre eigene winget-Quelle.",[10,400,402],{"id":401},"nächste-schritte","Nächste Schritte",[336,404,405,412,419,424,430,437],{},[339,406,407,411],{},[156,408,410],{"href":409},"\u002Fde\u002Fdocs\u002Fconcepts","Konzepte"," — das Vokabular, das der Rest der Doku voraussetzt.",[339,413,414,418],{},[156,415,417],{"href":416},"\u002Fde\u002Fdocs\u002Fpackages","Pakete & Manifeste"," — Import, Overlays, Freigabe, Installer-Ablage.",[339,420,421,423],{},[156,422,327],{"href":326}," — Site-Tokens, URL-Platzhalter, weitere Clients anbinden.",[339,425,426,429],{},[156,427,5],{"href":428},"\u002Fde\u002Fdocs\u002Fusers"," — Konten, Audit-Log, SSO\u002FMFA.",[339,431,432,436],{},[156,433,435],{"href":434},"\u002Fde\u002Fdocs\u002Fnodes","Edge-Nodes"," — Standorte aus einem lokalen Cache bedienen.",[339,438,439,443],{},[156,440,442],{"href":441},"\u002Fde\u002Fdocs\u002Fdeployment","Deployment"," — die Reverse-Proxy-Anforderung, Konfiguration, Betrieb.",[445,446,447],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":162,"searchDepth":163,"depth":163,"links":449},[450,451,452,453,454,455,456],{"id":187,"depth":163,"text":188},{"id":208,"depth":163,"text":209},{"id":218,"depth":163,"text":219},{"id":319,"depth":163,"text":320},{"id":330,"depth":163,"text":331},{"id":365,"depth":163,"text":366},{"id":401,"depth":163,"text":402},"Einen kvellman-Origin betreiben und in rund zehn Minuten den ersten Windows-Client daraus installieren lassen.",{},10,"\u002Fde\u002Fgetting-started",{"title":182,"description":457},"de\u002Fgetting-started","efY-bA_xWfJM0ZyxOUyr2K1KoiODKQlLPpomg4NpjOQ",{"id":465,"title":410,"body":466,"description":616,"extension":171,"meta":617,"nav":618,"navigation":174,"path":619,"seo":620,"stem":621,"__hash__":622},"docs\u002Fde\u002Fconcepts.md",{"type":7,"value":467,"toc":605},[468,471,477,481,500,504,515,519,532,536,542,546,563,567,581,585,592,596],[10,469,199],{"id":470},"origin",[15,472,473,474,476],{},"Der ",[193,475,199],{}," ist die kvellman-Installation, die Sie betreiben: Admin-Oberfläche,\nwinget-Source-API und Installer-Auslieferung. Ein Origin ist ein vollständiges, in sich\ngeschlossenes System — alles andere in dieser Doku (Sites, Nodes, Benutzer) wird darauf aufgesetzt.",[10,478,480],{"id":479},"paket-version-manifest","Paket, Version, Manifest",[15,482,483,484,487,488,491,492,495,496,499],{},"Ein ",[193,485,486],{},"Paket"," hat eine feste Kennung (z. B. ",[202,489,490],{},"Hersteller.App",") und eine oder mehrere ",[193,493,494],{},"Versionen",".\nDas ",[193,497,498],{},"Manifest"," einer Version beschreibt sie in den Formen, die winget selbst definiert —\nInstaller, Switches, Abhängigkeiten — und wird als strukturierte Daten gespeichert, nicht als\nDateien auf der Platte.",[10,501,503],{"id":502},"upstream-und-overlay","Upstream und Overlay",[15,505,506,507,510,511,514],{},"Beim Import eines Pakets bleibt sein ursprüngliches Manifest unangetastet als ",[193,508,509],{},"Upstream","-Stand\nerhalten. Jede Änderung, die Sie vornehmen, liegt als ",[193,512,513],{},"Overlay"," darüber, sodass Sie jederzeit den\nUnterschied zum Upstream sehen und darauf zurücksetzen können.",[10,516,518],{"id":517},"overlay-template","Overlay-Template",[15,520,483,521,523,524,527,528,531],{},[193,522,518],{}," verallgemeinert ein Overlay zu einer wiederverwendbaren Regel — zum\nBeispiel eine Installer-URL mit ",[202,525,526],{},"$VERSION","\u002F",[202,529,530],{},"$ARCH","-Platzhaltern — und wendet sie automatisch auf\njede künftige Version dieses Pakets an, sodass Sie dieselbe Änderung nicht bei jedem Release von\nHand wiederholen.",[10,533,535],{"id":534},"freigabe","Freigabe",[15,537,538,539,541],{},"Eine Version wird erst an Clients ausgeliefert, wenn sie ",[193,540,357],{}," ist. Das erzwingt die API\nselbst, nicht nur die Oberfläche — eine nicht freigegebene Version taucht in den Ergebnissen, die\nwinget erhält, schlicht nicht auf, egal wie sie in den Katalog kam.",[10,543,545],{"id":544},"site-und-site-token","Site und Site-Token",[15,547,548,549,552,553,556,557,560,561,160],{},"Eine ",[193,550,551],{},"Site"," ist ein benannter Kontext: ein Name, ein Standort, eine Standardsprache, eine\nRepository-URL. Ihr ",[193,554,555],{},"Token"," ist ihre Adresse — Clients erreichen sie unter\n",[202,558,559],{},"https:\u002F\u002Fihr-origin\u002Fapi\u002F\u003Csite-token>",". Die Werte einer Site lösen Platzhalter in Installer-URLs auf,\nsodass ein Manifest jeden Standort korrekt bedienen kann. Eine Site ist kein Mandant, kein separater\nKatalog, und für ihre Anlage wird nirgendwo etwas installiert — siehe ",[156,562,327],{"href":326},[10,564,566],{"id":565},"benutzer-und-rollen","Benutzer und Rollen",[15,568,569,570,572,573,575,576,578,579,160],{},"Jedes Konto hat eine Rolle: ",[193,571,36],{}," (Lesen), ",[193,574,39],{}," (bearbeiten und freigeben) oder\n",[193,577,42],{}," (verwaltet zusätzlich Benutzer, Sites, Nodes und die Lizenz). Siehe\n",[156,580,5],{"href":428},[10,582,584],{"id":583},"edge-node","Edge-Node",[15,586,483,587,589,590,160],{},[193,588,584],{}," ist eine Komponente, die an einem entfernten Standort läuft und winget-Clients\ndort aus einem lokalen Cache des Origin-Katalogs bedient, zentral vom Origin aus gesteuert. Siehe\n",[156,591,435],{"href":434},[10,593,595],{"id":594},"edition-und-berechtigungen","Edition und Berechtigungen",[15,597,598,599,602,603,160],{},"Die Kernplattform ist quelloffen. Einzelne Komponenten sind separat lizenziert und aktivieren sich,\nwenn Ihr Lizenz-Token die passende ",[193,600,601],{},"Berechtigung"," (Entitlement) trägt — siehe\n",[156,604,159],{"href":158},{"title":162,"searchDepth":163,"depth":163,"links":606},[607,608,609,610,611,612,613,614,615],{"id":470,"depth":163,"text":199},{"id":479,"depth":163,"text":480},{"id":502,"depth":163,"text":503},{"id":517,"depth":163,"text":518},{"id":534,"depth":163,"text":535},{"id":544,"depth":163,"text":545},{"id":565,"depth":163,"text":566},{"id":583,"depth":163,"text":584},{"id":594,"depth":163,"text":595},"Das Objektmodell und Vokabular, das der Rest der Dokumentation voraussetzt.",{},20,"\u002Fde\u002Fconcepts",{"title":410,"description":616},"de\u002Fconcepts","BXaPJzz9tZMODR_CvBzcbUaTi7VyBWHtV0ohrQB1uYU",{"id":624,"title":417,"body":625,"description":773,"extension":171,"meta":774,"nav":775,"navigation":174,"path":776,"seo":777,"stem":778,"__hash__":779},"docs\u002Fde\u002Fpackages.md",{"type":7,"value":626,"toc":765},[627,631,633,646,669,673,676,680,690,694,706,714,721,725,735,739,742,762],[10,628,630],{"id":629},"woher-pakete-kommen","Woher Pakete kommen",[15,632,334],{},[336,634,635,641],{},[339,636,637,640],{},[193,638,639],{},"Aus dem Upstream-Katalog importieren"," — Pakete → Import, den synchronisierten\nUpstream-Index durchsuchen, eine Version wählen, importieren.",[339,642,643,645],{},[193,644,350],{}," — Paket erstellen und Manifest-YAML direkt hochladen, für rein interne\nSoftware ohne Upstream-Eintrag.",[15,647,648,649,652,653,656,657,660,661,664,665,668],{},"Der Upstream-Index spiegelt das gemeinschaftlich gepflegte ",[202,650,651],{},"winget-pkgs","-Repository auf GitHub.\nSetzen Sie ",[202,654,655],{},"GITHUB_TOKEN"," (siehe ",[156,658,442],{"href":659},"\u002Fde\u002Fdocs\u002Fdeployment#konfiguration","), um das\nRate-Limit beim Import gegenüber der GitHub-API zu erhöhen; ",[202,662,663],{},"CATALOG_SYNC_ENABLED"," hält den\ndurchsuchbaren Index selbst auf dem in ",[202,666,667],{},"CATALOG_SYNC_INTERVAL_HOURS"," gesetzten Intervall aktuell.",[10,670,672],{"id":671},"validierung","Validierung",[15,674,675],{},"Jedes Manifest wird geparst und gegen die offiziellen winget-JSON-Schemas validiert — die Versionen\n1.0.0 bis 1.12.0 liegen der Anwendung bei. Ein Manifest, das nicht validiert, wird abgelehnt, bevor\nes gespeichert wird, mit einer Rückmeldung zum Schemafehler — dem fehlenden Feld, dem falschen Typ\noder dem ungültigen Enum-Wert — sodass Clients nie ein Manifest erhalten, das winget selbst nicht\nlesen kann.",[10,677,679],{"id":678},"overlays","Overlays",[15,681,682,683,686,687,689],{},"Das importierte Upstream-Manifest bleibt exakt so erhalten, wie es ankam. Jede Änderung, die Sie\nvornehmen — eine ",[202,684,685],{},"InstallerUrl"," umbiegen, den Installer-Scope ändern, Metadaten korrigieren — wird\nals ",[193,688,513],{}," darüber gespeichert. Sie können jederzeit den Unterschied zum Upstream ansehen oder\neine Version auf das unangetastete Upstream-Manifest zurücksetzen.",[10,691,693],{"id":692},"overlay-templates","Overlay-Templates",[15,695,696,697,700,701,527,703,705],{},"Dasselbe Overlay bei jedem neuen Release zu wiederholen ist mühsam, deshalb lässt sich ein Overlay\nzu einem ",[193,698,699],{},"Template"," verallgemeinern: die Änderung einmal mit ",[202,702,526],{},[202,704,530],{},"-Platzhaltern\nschreiben, und sie wird automatisch auf jede künftige Version dieses Pakets angewendet.",[228,707,712],{"className":708,"code":710,"language":711},[709],"language-text","InstallerUrl: https:\u002F\u002Ffiles.example.internal\u002F$ARCH\u002FApp-$VERSION.msi\n","text",[202,713,710],{"__ignoreMap":162},[15,715,716,717,720],{},"Importieren Sie ",[202,718,719],{},"App"," 2.3.0 heute, schreiben Sie das Template einmal — Version 2.4.0 hat das\npassende Overlay in einem halben Jahr schon angewendet, wenn sie eintrifft.",[10,722,724],{"id":723},"versionshistorie-und-freigabe","Versionshistorie und Freigabe",[15,726,727,728,731,732,734],{},"Jede Änderung an einer Version wird aufgezeichnet und lässt sich mit früheren Ständen vergleichen;\nsie landet zusammen mit dem ausführenden Konto im ",[156,729,137],{"href":730},"\u002Fde\u002Fdocs\u002Fusers#audit-log",". Eine\nVersion erreicht Clients erst, nachdem ein Reviewer oder Admin sie ",[193,733,357],{}," hat — das\nDashboard zeigt, was wartet. Das wird in der API erzwungen, nicht nur in der Oberfläche abgebildet.",[10,736,738],{"id":737},"installer-ablage","Installer-Ablage",[15,740,741],{},"Zwei Wege, wie ein Manifest auf einen Installer zeigt — Sie wählen pro Paket:",[743,744,745,751],"ol",{},[339,746,747,750],{},[193,748,749],{},"Auf dem Origin ablegen."," Die Datei liegt auf dem eigenen Speicher-Volume des Origin und wird\nvon dort ausgeliefert. Ihr SHA-256 wird bei jeder Auslieferung neu berechnet, sodass eine Datei,\ndie sich unerwartet auf der Platte verändert hat, an wingets Hash-Prüfung scheitert, statt\nstillschweigend zu installieren.",[339,752,753,756,757,761],{},[193,754,755],{},"Auf eine URL zeigen."," Das Manifest behält die Hersteller-URL oder eine interne — auch eine\nstandortspezifische Freigabe, aufgelöst über ",[156,758,760],{"href":759},"\u002Fde\u002Fdocs\u002Fsites#platzhalter","Site-Platzhalter",".\nkvellman löst die URL je Site auf; es kopiert die Datei dabei nirgendwohin.",[15,763,764],{},"kvellman spiegelt Installer nicht von sich aus nach S3, MinIO oder auf eine SMB-Freigabe — wenn Sie\ndas brauchen, hinterlegen Sie die entsprechende URL im Manifest und lassen Sie sie per Platzhalter\nauflösen.",{"title":162,"searchDepth":163,"depth":163,"links":766},[767,768,769,770,771,772],{"id":629,"depth":163,"text":630},{"id":671,"depth":163,"text":672},{"id":678,"depth":163,"text":679},{"id":692,"depth":163,"text":693},{"id":723,"depth":163,"text":724},{"id":737,"depth":163,"text":738},"Pakete importieren oder selbst anlegen, validieren, überlagern, per Template pflegen, freigeben und Installer ausliefern.",{},30,"\u002Fde\u002Fpackages",{"title":417,"description":773},"de\u002Fpackages","Ofx-VBYf4EWilWXw9szNF8QvJnl0-eGKtT1JI65StvM",{"id":781,"title":327,"body":782,"description":1015,"extension":171,"meta":1016,"nav":1017,"navigation":174,"path":1018,"seo":1019,"stem":1020,"__hash__":1021},"docs\u002Fde\u002Fsites.md",{"type":7,"value":783,"toc":1006},[784,788,791,852,856,862,871,874,878,881,931,938,965,968,972,982,986,989,993,996,1000,1003],[10,785,787],{"id":786},"was-eine-site-ist","Was eine Site ist",[15,789,790],{},"Eine Site ist ein benannter Kontext, kein Mandant und keine installierte Software:",[23,792,793,803],{},[26,794,795],{},[29,796,797,800],{},[32,798,799],{},"Feld",[32,801,802],{},"Wofür",[44,804,805,813,820,832,842],{},[29,806,807,810],{},[49,808,809],{},"Name",[49,811,812],{},"Ein lesbares Label (z. B. ein Gebäude oder eine Region).",[29,814,815,817],{},[49,816,555],{},[49,818,819],{},"Das URL-Segment, über das Clients diese Quelle erreichen.",[29,821,822,825],{},[49,823,824],{},"Standort",[49,826,827,828,831],{},"Löst den Platzhalter ",[202,829,830],{},"$LOCATION"," auf.",[29,833,834,837],{},[49,835,836],{},"Standardsprache",[49,838,827,839,831],{},[202,840,841],{},"$LANG",[29,843,844,847],{},[49,845,846],{},"Repository-URL",[49,848,827,849,831],{},[202,850,851],{},"$REPO_URL",[10,853,855],{"id":854},"die-quell-url","Die Quell-URL",[15,857,858,859,861],{},"Jede Site hat ihre eigene Quell-URL: ",[202,860,559],{},". Auf einem Client wird\nsie eingetragen wie jede winget-REST-Quelle:",[228,863,865],{"className":376,"code":864,"language":378,"meta":162,"style":162},"winget source add --name kvellman --type Microsoft.Rest --arg \"https:\u002F\u002Fihr-origin\u002Fapi\u002F\u003Csite-token>\"\n",[202,866,867],{"__ignoreMap":162},[236,868,869],{"class":238,"line":239},[236,870,864],{},[15,872,873],{},"Die API implementiert den winget-Source-REST-Vertrag direkt — kein Plugin und kein Agent auf\nClient-Seite ist beteiligt.",[10,875,877],{"id":876},"platzhalter","Platzhalter",[15,879,880],{},"Eine Installer-URL im Manifest kann auf die aktuelle Site verweisen:",[23,882,883,892],{},[26,884,885],{},[29,886,887,889],{},[32,888,877],{},[32,890,891],{},"Löst sich auf aus",[44,893,894,903,913,922],{},[29,895,896,900],{},[49,897,898],{},[202,899,851],{},[49,901,902],{},"Der Repository-URL der Site",[29,904,905,910],{},[49,906,907],{},[202,908,909],{},"$SITE",[49,911,912],{},"Dem Namen der Site",[29,914,915,919],{},[49,916,917],{},[202,918,830],{},[49,920,921],{},"Dem Standort der Site",[29,923,924,928],{},[49,925,926],{},[202,927,841],{},[49,929,930],{},"Der Standardsprache der Site",[15,932,933,934,937],{},"Beispiel: ein Manifest, ",[202,935,936],{},"InstallerUrl: $REPO_URL\u002Fsoftware\u002F$ARCH\u002FApp.msi",", aufgelöst für zwei Sites:",[336,939,940,954],{},[339,941,942,943,946,947,950,951],{},"Site ",[202,944,945],{},"muenchen"," mit Repository-URL ",[202,948,949],{},"https:\u002F\u002Ffiles.muenchen.internal"," →\n",[202,952,953],{},"https:\u002F\u002Ffiles.muenchen.internal\u002Fsoftware\u002Fx64\u002FApp.msi",[339,955,942,956,946,959,950,962],{},[202,957,958],{},"berlin",[202,960,961],{},"https:\u002F\u002Ffiles.berlin.internal",[202,963,964],{},"https:\u002F\u002Ffiles.berlin.internal\u002Fsoftware\u002Fx64\u002FApp.msi",[15,966,967],{},"Dasselbe Paket, dasselbe Manifest, die richtige Datei für jeden Standort.",[10,969,971],{"id":970},"clients-anbinden","Clients anbinden",[15,973,974,975,978,979,160],{},"Die Instructions-Seite in der Admin-Oberfläche zeigt für eine gegebene Site den fertigen\n",[202,976,977],{},"winget source add","-Befehl an — verschicken Sie diesen Link, statt den Token von Hand\nabzutippen. Zum Entfernen einer Quelle auf einem Client: ",[202,980,981],{},"winget source remove --name kvellman",[10,983,985],{"id":984},"tokens-rotieren-und-widerrufen","Tokens rotieren und widerrufen",[15,987,988],{},"Admin → Site-Tokens. Tragen Sie die Ersatzquelle auf den Clients ein, bevor Sie den alten Token\nwiderrufen — ein Widerruf bricht sofort jeden Client, der diese URL noch verwendet.",[10,990,992],{"id":991},"was-eine-site-auswählt","Was eine Site auswählt",[15,994,995],{},"Clients wählen eine Site allein über die verwendete URL — eine separate Auswahl über Subnetz oder\nZertifikat gibt es heute nicht. Wenn Sie unterschiedliches Verhalten je Netzsegment brauchen,\nsteuern Sie das an Ihrem Reverse-Proxy oder Ihrer Firewall und geben jedem Segment einen eigenen\nSite-Token und eine eigene URL.",[10,997,999],{"id":998},"wer-sie-erreichen-kann","Wer sie erreichen kann",[15,1001,1002],{},"Der Site-Token ist eine Adresse, kein Geheimnis — die winget-Source-API muss ohne Login erreichbar\nbleiben, weil winget selbst keine Authentifizierung mitschickt. Wer die URL erreicht, kann die\nQuelle durchsuchen und ihre Installer herunterladen. Wenn das für eine Site nicht akzeptabel ist,\nschränken Sie den Zugriff auf Netzwerkebene oder an Ihrem Reverse-Proxy ein — nicht, indem Sie den\nToken geheim halten.",[445,1004,1005],{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":162,"searchDepth":163,"depth":163,"links":1007},[1008,1009,1010,1011,1012,1013,1014],{"id":786,"depth":163,"text":787},{"id":854,"depth":163,"text":855},{"id":876,"depth":163,"text":877},{"id":970,"depth":163,"text":971},{"id":984,"depth":163,"text":985},{"id":991,"depth":163,"text":992},{"id":998,"depth":163,"text":999},"Was eine Site ist, die Quell-URL, URL-Platzhalter und wie Sie Clients anbinden.",{},40,"\u002Fde\u002Fsites",{"title":327,"description":1015},"de\u002Fsites","pCapY2SDWm9UZuVQp_dx6uUA0MnBam4raKOv7-HYqfI",{"id":4,"title":5,"body":1023,"description":170,"extension":171,"meta":1144,"nav":173,"navigation":174,"path":175,"seo":1145,"stem":177,"__hash__":178},{"type":7,"value":1024,"toc":1137},[1025,1027,1029,1031,1117,1119,1121,1123,1125,1127,1129,1131],[10,1026,13],{"id":12},[15,1028,17],{},[10,1030,21],{"id":20},[23,1032,1033,1045],{},[26,1034,1035],{},[29,1036,1037,1039,1041,1043],{},[32,1038],{},[32,1040,36],{},[32,1042,39],{},[32,1044,42],{},[44,1046,1047,1057,1067,1077,1087,1097,1107],{},[29,1048,1049,1051,1053,1055],{},[49,1050,51],{},[49,1052,54],{},[49,1054,54],{},[49,1056,54],{},[29,1058,1059,1061,1063,1065],{},[49,1060,63],{},[49,1062],{},[49,1064,54],{},[49,1066,54],{},[29,1068,1069,1071,1073,1075],{},[49,1070,74],{},[49,1072],{},[49,1074,54],{},[49,1076,54],{},[29,1078,1079,1081,1083,1085],{},[49,1080,85],{},[49,1082],{},[49,1084,54],{},[49,1086,54],{},[29,1088,1089,1091,1093,1095],{},[49,1090,96],{},[49,1092],{},[49,1094],{},[49,1096,54],{},[29,1098,1099,1101,1103,1105],{},[49,1100,107],{},[49,1102],{},[49,1104],{},[49,1106,54],{},[29,1108,1109,1111,1113,1115],{},[49,1110,118],{},[49,1112],{},[49,1114],{},[49,1116,54],{},[15,1118,127],{},[10,1120,96],{"id":130},[15,1122,133],{},[10,1124,137],{"id":136},[15,1126,140],{},[10,1128,144],{"id":143},[15,1130,147],{},[149,1132,1133],{"edition":151},[15,1134,154,1135,160],{},[156,1136,159],{"href":158},{"title":162,"searchDepth":163,"depth":163,"links":1138},[1139,1140,1141,1142,1143],{"id":12,"depth":163,"text":13},{"id":20,"depth":163,"text":21},{"id":130,"depth":163,"text":96},{"id":136,"depth":163,"text":137},{"id":143,"depth":163,"text":144},{},{"title":5,"description":170},{"id":1147,"title":435,"body":1148,"description":1268,"extension":171,"meta":1269,"nav":1270,"navigation":174,"path":1271,"seo":1272,"stem":1273,"__hash__":1274},"docs\u002Fde\u002Fnodes.md",{"type":7,"value":1149,"toc":1260},[1150,1154,1157,1161,1213,1216,1221,1225,1228,1232,1235,1239,1242,1251,1255,1258],[10,1151,1153],{"id":1152},"wozu-ein-edge-node","Wozu ein Edge-Node",[15,1155,1156],{},"Ohne einen läuft jede Installation an einem entfernten Standort über die Strecke zurück zum Origin.\nEin Edge-Node liefert die winget-API und Installer-Downloads am Standort lokal aus und holt beim\nOrigin nur bei Bedarf nach.",[10,1158,1160],{"id":1159},"was-wo-läuft","Was wo läuft",[23,1162,1163,1173],{},[26,1164,1165],{},[29,1166,1167,1170],{},[32,1168,1169],{},"Läuft auf dem Origin (Teil der Anwendung, die Sie bereits betreiben)",[32,1171,1172],{},"Läuft am Standort (Enterprise-Edition)",[44,1174,1175,1183,1191,1199,1206],{},[29,1176,1177,1180],{},[49,1178,1179],{},"Nodes enrollen und widerrufen, Enrollment-Keys ausstellen",[49,1181,1182],{},"Der Edge-Node selbst — liefert winget-API und Installer-Downloads lokal aus",[29,1184,1185,1188],{},[49,1186,1187],{},"Health und Heartbeat, Node-Status",[49,1189,1190],{},"Cacht vom Origin beim ersten Zugriff",[29,1192,1193,1196],{},[49,1194,1195],{},"Paket- und Tag-Scope je Node",[49,1197,1198],{},"Bedient jede weitere Anfrage danach lokal",[29,1200,1201,1204],{},[49,1202,1203],{},"Installer-Filter (Architektur, Scope)",[49,1205],{},[29,1207,1208,1211],{},[49,1209,1210],{},"Push, Pre-Stage, Evict",[49,1212],{},[15,1214,1215],{},"Die Node-Verwaltung — Enrollment, Scope, Filter, Push\u002FPre-Stage, Evict und Health — ist Teil der\nAnwendung, die Sie bereits betreiben.",[149,1217,1218],{"edition":151},[15,1219,1220],{},"Der Edge-Node selbst — der Teil, der am Standort läuft und Clients dort beantwortet — ist Teil der\nEnterprise-Edition und wird separat an jedem Standort bereitgestellt. Er verbindet sich mit einem\nEnrollment-Key, den Sie im selben Bildschirm erzeugen, zu Ihrem Origin zurück.",[10,1222,1224],{"id":1223},"einen-node-enrollen","Einen Node enrollen",[15,1226,1227],{},"Admin → Edge-Nodes → einen anlegen, das erzeugt einen einmaligen Enrollment-Key. Den Node am\nStandort mit diesem Key starten; er tauscht ihn beim ersten Kontakt gegen einen dauerhaften Token\nein, optional mit einem vom internen CA des Origin ausgestellten Client-Zertifikat für mTLS bei\nspäteren Anfragen.",[10,1229,1231],{"id":1230},"scope-und-steuerung","Scope und Steuerung",[15,1233,1234],{},"Für jeden Node legen Sie fest, welche Pakete oder Tags er trägt, und filtern Installer nach\nArchitektur und Scope, damit ein kleiner Standort nicht mehr cached als nötig. Caching läuft\nansonsten lazy: ein Node holt beim ersten Request nach und bedient jeden weiteren Client danach aus\ndem eigenen Cache. Pre-Stage überspringt diesen ersten langsamen Request — pushen Sie eine Version\nvor einem Rollout, sodass der erste Client an diesem Standort bereits lokal bedient wird. Evict\nerzwingt ein erneutes Nachladen — nutzen Sie es, nachdem Sie eine Installer-Datei unter derselben\nURL ersetzt haben, oder um Platz auf einem Node mit knappem Speicher freizugeben. Den Status eines\nNode sehen Sie im Dashboard.",[10,1236,1238],{"id":1237},"auf-der-client-seite","Auf der Client-Seite",[15,1240,1241],{},"Clients am Standort tragen die eigene Quell-URL des Node ein, genauso wie die des Origin:",[228,1243,1245],{"className":376,"code":1244,"language":378,"meta":162,"style":162},"winget source add --name kvellman --type Microsoft.Rest --arg \"https:\u002F\u002Fnode.beispiel-standort.internal\u002Fapi\u002F\u003Csite-token>\"\n",[202,1246,1247],{"__ignoreMap":162},[236,1248,1249],{"class":238,"line":239},[236,1250,1244],{},[10,1252,1254],{"id":1253},"anforderungen-am-standort","Anforderungen am Standort",[15,1256,1257],{},"Ein Host, der einen Container ausführen kann, ausgehende Erreichbarkeit zum Origin und ein\nvertrauenswürdiges HTTPS-Zertifikat für die eigene URL des Node — wingets HTTPS-Anforderung gilt\nfür einen Node genauso wie für den Origin.",[445,1259,1005],{},{"title":162,"searchDepth":163,"depth":163,"links":1261},[1262,1263,1264,1265,1266,1267],{"id":1152,"depth":163,"text":1153},{"id":1159,"depth":163,"text":1160},{"id":1223,"depth":163,"text":1224},{"id":1230,"depth":163,"text":1231},{"id":1237,"depth":163,"text":1238},{"id":1253,"depth":163,"text":1254},"winget-Clients an einem entfernten Standort aus einem lokalen Cache Ihres Origin bedienen.",{},60,"\u002Fde\u002Fnodes",{"title":435,"description":1268},"de\u002Fnodes","DNQpASvBVwwmlnasZlX3WnLqoDYJH0Ap0lgcjcXFcx8",{"id":1276,"title":442,"body":1277,"description":1694,"extension":171,"meta":1695,"nav":1696,"navigation":174,"path":1697,"seo":1698,"stem":1699,"__hash__":1700},"docs\u002Fde\u002Fdeployment.md",{"type":7,"value":1278,"toc":1679},[1279,1283,1303,1307,1313,1317,1320,1323,1348,1351,1355,1360,1371,1400,1404,1414,1439,1443,1450,1518,1522,1631,1635,1642,1646,1649,1653,1656,1660,1666,1676],[10,1280,1282],{"id":1281},"was-die-anwendung-braucht","Was die Anwendung braucht",[336,1284,1285,1291,1297],{},[339,1286,1287,1290],{},[193,1288,1289],{},"PostgreSQL"," — der gesamte Zustand des Origin.",[339,1292,1293,1296],{},[193,1294,1295],{},"Ein dauerhaftes Volume"," — für Installer, die Sie auf dem Origin ablegen.",[339,1298,1299,1302],{},[193,1300,1301],{},"Etwas davor, das HTTPS terminiert."," Die Anwendung selbst ist ein einfacher HTTP-Server auf\nPort 3000; sie kümmert sich nicht um TLS.",[10,1304,1306],{"id":1305},"https-ist-nicht-optional","HTTPS ist nicht optional",[15,1308,1309,1310,1312],{},"winget verweigert eine REST-Quelle, die nicht über HTTPS mit einem vertrauenswürdigen Zertifikat\nläuft — bei neueren winget-Versionen auch für ",[202,1311,215],{},". Eine interne CA ist in Ordnung, solange\nIhre Clients ihr vertrauen; ein nicht vertrauenswürdiges selbstsigniertes Zertifikat nicht.",[10,1314,1316],{"id":1315},"der-reverse-proxy","Der Reverse-Proxy",[15,1318,1319],{},"kvellman lauscht auf Port 3000 und spricht einfaches HTTP. Es terminiert kein TLS und kümmert sich\nnicht darum, was davor steht. Alles, was HTTPS terminieren und an ein HTTP-Upstream weiterleiten\nkann, funktioniert: nginx, HAProxy, Apache, eine Appliance, Ihr vorhandener Ingress.",[15,1321,1322],{},"Was auch immer Sie einsetzen, muss:",[336,1324,1325,1328,1331,1342,1345],{},[339,1326,1327],{},"an Port 3000 der Anwendung weiterleiten",[339,1329,1330],{},"ein Zertifikat ausliefern, dem die Clients vertrauen",[339,1332,1333,1334,1337,1338,1341],{},"Host und Protokoll des ursprünglichen Requests durchreichen (",[202,1335,1336],{},"Host",", ",[202,1339,1340],{},"X-Forwarded-Proto",")",[339,1343,1344],{},"Response-Bodies nicht puffern oder begrenzen — Installer sind groß",[339,1346,1347],{},"lang laufende Downloads zulassen (großzügige Read-\u002FSend-Timeouts)",[15,1349,1350],{},"Das ist die gesamte Integrationsfläche.",[10,1352,1354],{"id":1353},"beispiele-im-detail","Beispiele im Detail",[1356,1357,1359],"h3",{"id":1358},"ein-compose-stack-mit-gebündeltem-proxy","Ein Compose-Stack mit gebündeltem Proxy",[15,1361,1362,1363,1366,1367,1370],{},"Die Standard-",[202,1364,1365],{},"docker-compose.yml"," bündelt ",[193,1368,1369],{},"Caddy",", das automatisch ein Let's-Encrypt-Zertifikat\nbezieht. Nutzen Sie sie, wenn der Host öffentlich erreichbar ist und Sie noch keinen Proxy\nbetreiben.",[228,1372,1374],{"className":230,"code":1373,"language":232,"meta":162,"style":162},"cp .env.deploy.example .env.deploy   # DOMAIN, NUXT_SESSION_PASSWORD, POSTGRES_PASSWORD setzen\ndocker compose --env-file .env.deploy up -d\n",[202,1375,1376,1386],{"__ignoreMap":162},[236,1377,1378,1380,1382,1384],{"class":238,"line":239},[236,1379,279],{"class":242},[236,1381,282],{"class":246},[236,1383,285],{"class":246},[236,1385,289],{"class":288},[236,1387,1388,1390,1392,1394,1396,1398],{"class":238,"line":163},[236,1389,295],{"class":242},[236,1391,298],{"class":246},[236,1393,301],{"class":246},[236,1395,285],{"class":246},[236,1397,306],{"class":246},[236,1399,309],{"class":246},[1356,1401,1403],{"id":1402},"routing-über-einen-vorhandenen-ingress","Routing über einen vorhandenen Ingress",[15,1405,1406,1409,1410,1413],{},[202,1407,1408],{},"docker-compose.traefik.yml"," kommt ohne gebündelten Proxy — die Anwendung hängt sich in Ihr\nvorhandenes ",[193,1411,1412],{},"Traefik","-Netz und wird per Labels geroutet. Nutzen Sie das, wenn Port 80\u002F443 schon\netwas anderem gehören.",[228,1415,1417],{"className":230,"code":1416,"language":232,"meta":162,"style":162},"docker compose -f docker-compose.traefik.yml --env-file .env.deploy up -d\n",[202,1418,1419],{"__ignoreMap":162},[236,1420,1421,1423,1425,1428,1431,1433,1435,1437],{"class":238,"line":239},[236,1422,295],{"class":242},[236,1424,298],{"class":246},[236,1426,1427],{"class":246}," -f",[236,1429,1430],{"class":246}," docker-compose.traefik.yml",[236,1432,301],{"class":246},[236,1434,285],{"class":246},[236,1436,306],{"class":246},[236,1438,309],{"class":246},[1356,1440,1442],{"id":1441},"jeder-andere-proxy","Jeder andere Proxy",[15,1444,1445,1446,1449],{},"Der Anwendung ist es egal. Zeigen Sie einen beliebigen HTTPS-terminierenden Proxy auf Port 3000 —\nzum Beispiel ",[193,1447,1448],{},"nginx",":",[228,1451,1454],{"className":1452,"code":1453,"language":1448,"meta":162,"style":162},"language-nginx shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","server {\n  listen 443 ssl;\n  server_name ihre-domain;\n  location \u002F {\n    proxy_pass http:\u002F\u002Fkvellman:3000;\n    proxy_set_header Host $host;\n    proxy_set_header X-Forwarded-Proto $scheme;\n    proxy_request_buffering off;\n    client_max_body_size 0;\n  }\n}\n",[202,1455,1456,1461,1466,1471,1477,1483,1489,1495,1501,1507,1512],{"__ignoreMap":162},[236,1457,1458],{"class":238,"line":239},[236,1459,1460],{},"server {\n",[236,1462,1463],{"class":238,"line":163},[236,1464,1465],{},"  listen 443 ssl;\n",[236,1467,1468],{"class":238,"line":292},[236,1469,1470],{},"  server_name ihre-domain;\n",[236,1472,1474],{"class":238,"line":1473},4,[236,1475,1476],{},"  location \u002F {\n",[236,1478,1480],{"class":238,"line":1479},5,[236,1481,1482],{},"    proxy_pass http:\u002F\u002Fkvellman:3000;\n",[236,1484,1486],{"class":238,"line":1485},6,[236,1487,1488],{},"    proxy_set_header Host $host;\n",[236,1490,1492],{"class":238,"line":1491},7,[236,1493,1494],{},"    proxy_set_header X-Forwarded-Proto $scheme;\n",[236,1496,1498],{"class":238,"line":1497},8,[236,1499,1500],{},"    proxy_request_buffering off;\n",[236,1502,1504],{"class":238,"line":1503},9,[236,1505,1506],{},"    client_max_body_size 0;\n",[236,1508,1509],{"class":238,"line":459},[236,1510,1511],{},"  }\n",[236,1513,1515],{"class":238,"line":1514},11,[236,1516,1517],{},"}\n",[10,1519,1521],{"id":1520},"konfiguration","Konfiguration",[23,1523,1524,1534],{},[26,1525,1526],{},[29,1527,1528,1531],{},[32,1529,1530],{},"Variable",[32,1532,1533],{},"Zweck",[44,1535,1536,1546,1559,1569,1579,1593,1604,1613],{},[29,1537,1538,1543],{},[49,1539,1540],{},[202,1541,1542],{},"DOMAIN",[49,1544,1545],{},"Öffentlicher Hostname (von der gebündelten Caddy-Compose-Datei für ihr Zertifikat genutzt).",[29,1547,1548,1553],{},[49,1549,1550],{},[202,1551,1552],{},"NUXT_SESSION_PASSWORD",[49,1554,1555,1556,160],{},"Sealing-Secret für das Session-Cookie, ≥32 Zeichen. Erzeugen mit ",[202,1557,1558],{},"openssl rand -hex 32",[29,1560,1561,1566],{},[49,1562,1563],{},[202,1564,1565],{},"POSTGRES_PASSWORD",[49,1567,1568],{},"Passwort für den gebündelten PostgreSQL-Container.",[29,1570,1571,1576],{},[49,1572,1573],{},[202,1574,1575],{},"KVELLMAN_IMAGE",[49,1577,1578],{},"Ein vorgebautes Image zum Ziehen, statt auf dem Host zu bauen.",[29,1580,1581,1590],{},[49,1582,1583,1586,1587],{},[202,1584,1585],{},"TELEMETRY_ENABLED"," \u002F ",[202,1588,1589],{},"TELEMETRY_RETENTION_DAYS",[49,1591,1592],{},"Nutzungstelemetrie, standardmäßig aus.",[29,1594,1595,1601],{},[49,1596,1597,1586,1599],{},[202,1598,663],{},[202,1600,667],{},[49,1602,1603],{},"Geplanter Upstream-Katalog-Sync, standardmäßig aus.",[29,1605,1606,1610],{},[49,1607,1608],{},[202,1609,655],{},[49,1611,1612],{},"Erhöht das Rate-Limit beim Import aus winget-pkgs.",[29,1614,1615,1626],{},[49,1616,1617,1586,1620,1586,1623],{},[202,1618,1619],{},"TRAEFIK_NETWORK",[202,1621,1622],{},"TRAEFIK_ENTRYPOINT",[202,1624,1625],{},"TRAEFIK_CERTRESOLVER",[49,1627,1628,1629,160],{},"Nur für ",[202,1630,1408],{},[10,1632,1634],{"id":1633},"betrieb-ohne-die-compose-dateien","Betrieb ohne die Compose-Dateien",[15,1636,1637,1638,1641],{},"Eigenes PostgreSQL und eigene Orchestrierung mitzubringen ist kein Problem: das Image starten,\n",[202,1639,1640],{},"DATABASE_URL"," auf Ihre Datenbank zeigen lassen und Port 3000 Ihrem Proxy exponieren. Migrationen\nlaufen beim Start automatisch — es gibt keinen separaten Migrationsschritt zu skripten.",[10,1643,1645],{"id":1644},"backups-und-upgrades","Backups und Upgrades",[15,1647,1648],{},"Der gesamte Zustand einer Installation ist die PostgreSQL-Datenbank plus das Installer-Volume —\nsichern Sie beide. Ein Upgrade ist das Ziehen eines neueren Image-Tags und ein Neustart; Migrationen\nlaufen beim Start.",[10,1650,1652],{"id":1651},"telemetrie","Telemetrie",[15,1654,1655],{},"Standardmäßig aus, per Umgebungsvariable aktivierbar. Erfasst Suchen, Manifest-Abrufe und\nInstaller-Downloads, stündlich innerhalb des Anwendungsprozesses selbst zusammengefasst, mit\nLöschung der Rohereignisse nach der von Ihnen konfigurierten Aufbewahrungsdauer. Für den Betrieb ist\nkeine Queue, kein Cache und kein zusätzlicher Dienst nötig. Die zusammengefassten Zahlen erscheinen\nin der Admin-Oberfläche als Dashboards, aufgeschlüsselt nach Site und nach winget-Client-Version.",[10,1657,1659],{"id":1658},"air-gap-betrieb","Air-Gap-Betrieb",[15,1661,1662,1663,1665],{},"Die Anwendung macht für den Betrieb keine ausgehenden Aufrufe, und die Lizenzprüfung ist\nvollständig lokal — sie läuft also vollständig getrennt vom Internet. Der Upstream-Katalog-Sync und\nder Manifest-Import von GitHub brauchen Internetzugang — lassen Sie ",[202,1664,663],{}," aus und\nimportieren Sie Manifeste von Hand, wenn der Host keinen hat.",[1667,1668,1669],"blockquote",{},[15,1670,1671,1672,1675],{},"Die vollständige Schritt-für-Schritt-Anleitung (Origin, Edge-Node unter WSL, TLS für\nLAN\u002Flocalhost, Registry-Workflow) steht in ",[202,1673,1674],{},"DEPLOYMENT.md"," im Open-Core-Repository — diese Seite\nbeschreibt die Grobform davon.",[445,1677,1678],{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}",{"title":162,"searchDepth":163,"depth":163,"links":1680},[1681,1682,1683,1684,1689,1690,1691,1692,1693],{"id":1281,"depth":163,"text":1282},{"id":1305,"depth":163,"text":1306},{"id":1315,"depth":163,"text":1316},{"id":1353,"depth":163,"text":1354,"children":1685},[1686,1687,1688],{"id":1358,"depth":292,"text":1359},{"id":1402,"depth":292,"text":1403},{"id":1441,"depth":292,"text":1442},{"id":1520,"depth":163,"text":1521},{"id":1633,"depth":163,"text":1634},{"id":1644,"depth":163,"text":1645},{"id":1651,"depth":163,"text":1652},{"id":1658,"depth":163,"text":1659},"Den Origin hinter einem beliebigen HTTPS-terminierenden Reverse-Proxy betreiben — die Anforderung, plus drei Beispiele im Detail.",{},70,"\u002Fde\u002Fdeployment",{"title":442,"description":1694},"de\u002Fdeployment","fmfT2zvqKbsORLrOb6j40pX3Z9LJekLfpz8OrLHMr3k",{"id":1702,"title":1703,"body":1704,"description":1797,"extension":171,"meta":1798,"nav":1799,"navigation":174,"path":1800,"seo":1801,"stem":1802,"__hash__":1803},"docs\u002Fde\u002Farchitecture.md","Architektur",{"type":7,"value":1705,"toc":1788},[1706,1710,1713,1733,1736,1740,1743,1747,1754,1758,1763,1767,1774,1778,1781,1785],[10,1707,1709],{"id":1708},"request-pfad","Request-Pfad",[15,1711,1712],{},"Ein winget-Client spricht HTTPS mit Ihrem Reverse-Proxy, der einfaches HTTP an den Origin\nweiterleitet. Der Origin liest und schreibt in PostgreSQL sowie — für auf ihm abgelegte Installer —\nin sein eigenes Speicher-Volume.",[336,1714,1715,1721,1727],{},[339,1716,1717,1720],{},[202,1718,1719],{},"GET \u002Fapi\u002F{siteToken}\u002Finformation"," — Quell-Metadaten und unterstützte Versionen.",[339,1722,1723,1726],{},[202,1724,1725],{},"POST \u002Fapi\u002F{siteToken}\u002FmanifestSearch"," — Volltextsuche.",[339,1728,1729,1732],{},[202,1730,1731],{},"GET \u002Fapi\u002F{siteToken}\u002FpackageManifests\u002F{id}"," — Manifest-Auslieferung mit serverseitiger\nPlatzhalter-Auflösung.",[15,1734,1735],{},"Es werden ausschließlich freigegebene Versionen ausgeliefert.",[10,1737,1739],{"id":1738},"datenmodell","Datenmodell",[15,1741,1742],{},"Pakete, Versionen und Manifeste sind relational gespeichert, in Formen, die wingets eigenes\nManifest-Schema spiegeln, zusammen mit dem unangetasteten Upstream-Snapshot und jedem Overlay\ndarüber. Sites, Edge-Nodes, Benutzer, das Audit-Log und Telemetrie-Ereignisse liegen in derselben\nDatenbank. Eine Datenbank ist der gesamte Zustand einer Installation, plus das Installer-Volume.",[10,1744,1746],{"id":1745},"installer-auslieferung","Installer-Auslieferung",[15,1748,1749,1750,1753],{},"Auf dem Origin abgelegte Installer werden von seinem eigenen Volume unter ",[202,1751,1752],{},"\u002Fdl\u002F..."," ausgeliefert,\nmit bei jeder Auslieferung neu berechnetem SHA-256.",[10,1755,1757],{"id":1756},"node-steuerungsebene","Node-Steuerungsebene",[15,1759,1760,1761,160],{},"Der Origin enrollt, scopt und überwacht Edge-Nodes; er betreibt den Node selbst nicht. Siehe\n",[156,1762,435],{"href":434},[10,1764,1766],{"id":1765},"erweiterungsmodell","Erweiterungsmodell",[15,1768,1769,1770,1773],{},"Auth-Provider registrieren sich über einen Plugin-Host und werden über Berechtigungen\nfreigeschaltet, die aus dem Lizenz-Token gelesen werden — ein Plugin aktiviert sich erst, wenn die\npassende Berechtigung vorliegt. ",[202,1771,1772],{},"@kvellman\u002Fplugin-sdk"," ist die öffentliche Typ-Oberfläche dafür.",[10,1775,1777],{"id":1776},"stack","Stack",[15,1779,1780],{},"Nuxt 4 (Vue 3 + Nitro), TypeScript, PostgreSQL mit Drizzle ORM, Zod und die offiziellen\nwinget-JSON-Schemas (via ajv) für die Manifest-Validierung, Nuxt UI, deutsche und englische\nOberfläche. Ausschließlich On-Premise — selbst hostbar, inklusive Air-Gap-Betrieb.",[10,1782,1784],{"id":1783},"umfang-einer-installation","Umfang einer Installation",[15,1786,1787],{},"Ein Anwendungsprozess übernimmt Requests, Installer-Auslieferung und geplante Arbeit\n(Telemetrie-Rollup, Katalog-Sync). Installer liegen auf einem lokalen Volume oder werden per URL\nreferenziert. Konten sind in der Core-Edition an die jeweilige Installation gebunden. Die\nKomponenten einer Installation sind der Anwendungscontainer und eine Datenbank.",{"title":162,"searchDepth":163,"depth":163,"links":1789},[1790,1791,1792,1793,1794,1795,1796],{"id":1708,"depth":163,"text":1709},{"id":1738,"depth":163,"text":1739},{"id":1745,"depth":163,"text":1746},{"id":1756,"depth":163,"text":1757},{"id":1765,"depth":163,"text":1766},{"id":1776,"depth":163,"text":1777},{"id":1783,"depth":163,"text":1784},"Request-Pfad, Datenmodell, Auslieferung, Erweiterungsmodell und der Umfang einer einzelnen Installation.",{},80,"\u002Fde\u002Farchitecture",{"title":1703,"description":1797},"de\u002Farchitecture","0_7bs-qTCtrpnHRhHaE1PXgUOSxk6aSaYMs-Kmi_xYU",{"id":1805,"title":159,"body":1806,"description":1981,"extension":171,"meta":1982,"nav":1983,"navigation":174,"path":1984,"seo":1985,"stem":1986,"__hash__":1987},"docs\u002Fde\u002Feditions-licensing.md",{"type":7,"value":1807,"toc":1976},[1808,1812,1826,1832,1837,1903,1910,1914,1921,1953,1956,1960,1963],[10,1809,1811],{"id":1810},"open-core","Open Core",[15,1813,1814,1815,1817,1818,1821,1822,1825],{},"kvellman ist ",[193,1816,1811],{},". Die Plattform — inklusive Mehrbenutzer-Konten mit Rollen und dem\nFreigabe-Workflow — ist quelloffen unter ",[193,1819,1820],{},"Apache-2.0",". Eine kleine Zahl von Komponenten ist\n",[193,1823,1824],{},"lizenzierte Plugins",", die sich nur mit gültiger Enterprise-Berechtigung aktivieren.",[149,1827,1829],{"edition":1828},"community",[15,1830,1831],{},"Alles, was Sie für einen produktiven Origin brauchen: die winget-Source-API, Manifeste, Overlays und Upstream-Import, Mehrbenutzer-Konten mit den Rollen Viewer\u002FReviewer\u002FAdmin, der Freigabe-Workflow samt Audit-Log, und Air-Gap-Betrieb.",[149,1833,1834],{"edition":151},[15,1835,1836],{},"Ergänzt SSO (OIDC) und MFA (TOTP) als lizenzierte Auth-Plugins sowie die Edge-Node-Komponente für weitere Standorte aus einem lokalen Cache.",[23,1838,1839,1851],{},[26,1840,1841],{},[29,1842,1843,1845,1848],{},[32,1844],{},[32,1846,1847],{},"Community",[32,1849,1850],{},"Enterprise",[44,1852,1853,1863,1874,1884,1895],{},[29,1854,1855,1858,1860],{},[49,1856,1857],{},"Lizenz",[49,1859,1820],{},[49,1861,1862],{},"Kommerzielles Abo",[29,1864,1865,1868,1871],{},[49,1866,1867],{},"Konten",[49,1869,1870],{},"Mehrbenutzer, Rollen (Viewer\u002FReviewer\u002FAdmin)",[49,1872,1873],{},"Dasselbe, plus SSO (OIDC) & MFA (TOTP)",[29,1875,1876,1879,1882],{},[49,1877,1878],{},"Freigabe-Workflow & Audit-Log",[49,1880,1881],{},"Enthalten",[49,1883,1881],{},[29,1885,1886,1889,1892],{},[49,1887,1888],{},"Weitere Standorte",[49,1890,1891],{},"—",[49,1893,1894],{},"Edge-Node-Komponente",[29,1896,1897,1899,1901],{},[49,1898,1659],{},[49,1900,1881],{},[49,1902,1881],{},[15,1904,1905,1906,160],{},"Der vollständige Vergleich steht unter ",[156,1907,1909],{"href":1908},"\u002Fpricing","Preise",[10,1911,1913],{"id":1912},"wie-die-lizenzierung-funktioniert","Wie die Lizenzierung funktioniert",[15,1915,1916,1917,1920],{},"Enterprise-Funktionen werden über eine ",[193,1918,1919],{},"offline, signaturbasierte"," Lizenz freigeschaltet — kein\nAktivierungsserver, funktioniert also air-gapped:",[743,1922,1923,1929,1936,1950],{},[339,1924,1925,1926,160],{},"Eine Lizenz ist ein vom Hersteller ",[193,1927,1928],{},"Ed25519-signiertes Token",[339,1930,1931,1932,1935],{},"Das Produkt enthält nur den ",[193,1933,1934],{},"öffentlichen Schlüssel"," und prüft das Token lokal.",[339,1937,1938,1939,1942,1943,1337,1946,1949],{},"Das Token nennt Kunde und aktive ",[193,1940,1941],{},"Berechtigungen"," (z. B. ",[202,1944,1945],{},"sso",[202,1947,1948],{},"mfa",") sowie ein Ablaufdatum.",[339,1951,1952],{},"Ein Admin fügt das Token in der UI ein; passende Plugins werden sofort aktiv — ohne Neustart,\nohne Internet.",[15,1954,1955],{},"Da die Prüfung lokal erfolgt, kann selbst der vollständige Open-Source-Code keine gültige Lizenz\nfälschen, solange der private Schlüssel des Herstellers geheim bleibt.",[10,1957,1959],{"id":1958},"entwickler-pakete","Entwickler-Pakete",[15,1961,1962],{},"Die gemeinsamen, öffentlichen Bausteine liegen auf npm unter Apache-2.0:",[336,1964,1965,1971],{},[339,1966,1967,1970],{},[202,1968,1969],{},"@kvellman\u002Fwinget-contract"," — der von Origin und Nodes geteilte winget-REST-\u002FTypen-Vertrag.",[339,1972,1973,1975],{},[202,1974,1772],{}," — Typen zum Bauen von Auth-\u002FEntitlement-Plugins.",{"title":162,"searchDepth":163,"depth":163,"links":1977},[1978,1979,1980],{"id":1810,"depth":163,"text":1811},{"id":1912,"depth":163,"text":1913},{"id":1958,"depth":163,"text":1959},"Open-Core-Modell — was im Community-Kern steckt vs. lizenzierte Enterprise-Komponenten, und wie die Lizenzierung funktioniert.",{},90,"\u002Fde\u002Feditions-licensing",{"title":159,"description":1981},"de\u002Feditions-licensing","ak0l1f3V3B9pGvW8BW1u4BgTSyypUJarWZNR_iljsAw",1787516842049]