[{"data":1,"prerenderedAt":2061},["ShallowReactive",2],{"search-de":3,"content-de-developer\u002Fself-hosting-config":4,"surround-de-\u002Fdeveloper\u002Fself-hosting-config":2055},[],{"id":5,"title":6,"body":7,"description":2047,"extension":2048,"meta":2049,"navigation":2050,"path":2051,"seo":2052,"stem":2053,"__hash__":2054},"content_de\u002F3.developer\u002F31.self-hosting-config.md","Self-Hosting-Konfiguration",{"type":8,"value":9,"toc":2027},"minimark",[10,20,25,62,66,72,77,141,145,148,215,219,253,508,512,515,624,641,670,674,715,719,722,781,801,805,816,920,958,961,964,1034,1038,1041,1121,1156,1183,1235,1239,1314,1318,1326,1436,1465,1493,1497,1580,1587,1591,1833,1853,1872,1892,1896,2023],[11,12,13,14,19],"p",{},"Diese Seite ist die vollständige Konfigurationsreferenz für eine selbst gehostete Owlat-Instanz. Eine Schritt-für-Schritt-Einrichtung finden Sie unter ",[15,16,18],"a",{"href":17},"\u002Fdeveloper\u002Fself-hosting","Self-Hosting",".",[21,22,24],"h2",{"id":23},"zwei-konfigurationsebenen","Zwei Konfigurationsebenen",[26,27,30,38],"callout",{"title":28,"type":29},"Docker-.env vs. Convex-Umgebungsvariablen","warning",[11,31,32,33,37],{},"Owlat nutzt ",[34,35,36],"strong",{},"zwei getrennte Konfigurationsebenen",". Sie zu verwechseln ist der häufigste Fehler bei der Einrichtung.",[39,40,41,52],"ul",{},[42,43,44,51],"li",{},[34,45,46,47],{},"Docker-",[48,49,50],"code",{},".env"," — wird von Docker Compose beim Start der Container gelesen. Steuert Ports, zwischen Containern geteilte Secrets und die vom Browser aufgerufenen URLs.",[42,53,54,57,58,61],{},[34,55,56],{},"Convex-Umgebungsvariablen"," — werden von den Serverless-Functions innerhalb des Convex-Backends gelesen. Werden nach dem Deployment über ",[48,59,60],{},"npx convex env set"," gesetzt. Steuern das Anwendungsverhalten: E-Mail-Provider, Auth-Secrets, Absenderidentität, Integrationen.",[21,63,65],{"id":64},"docker-umgebungsvariablen","Docker-Umgebungsvariablen",[11,67,68,69,71],{},"Diese gehören in die Datei ",[48,70,50],{}," im Projektstammverzeichnis. Docker Compose liest sie beim Starten der Container.",[73,74,76],"h3",{"id":75},"convex-backend","Convex-Backend",[78,79,80,99],"table",{},[81,82,83],"thead",{},[84,85,86,90,93,96],"tr",{},[87,88,89],"th",{},"Variable",[87,91,92],{},"Erforderlich",[87,94,95],{},"Standard",[87,97,98],{},"Beschreibung",[100,101,102,123],"tbody",{},[84,103,104,110,113,116],{},[105,106,107],"td",{},[48,108,109],{},"INSTANCE_SECRET",[105,111,112],{},"Ja",[105,114,115],{},"—",[105,117,118,119,122],{},"Instanzidentität des Convex-Backends. Mit ",[48,120,121],{},"openssl rand -hex 32"," erzeugen.",[84,124,125,130,132,134],{},[105,126,127],{},[48,128,129],{},"CONVEX_ADMIN_KEY",[105,131,112],{},[105,133,115],{},[105,135,136,137,140],{},"Admin-Key zum Deployen der Functions. Wird nach dem ersten Start über ",[48,138,139],{},"docker compose exec convex .\u002Fgenerate_admin_key.sh"," erzeugt.",[73,142,144],{"id":143},"öffentliche-urls","Öffentliche URLs",[11,146,147],{},"Diese müssen aus dem Browser des Nutzers erreichbar sein — verwenden Sie keine Docker-internen Hostnamen.",[78,149,150,162],{},[81,151,152],{},[84,153,154,156,158,160],{},[87,155,89],{},[87,157,92],{},[87,159,95],{},[87,161,98],{},[100,163,164,181,198],{},[84,165,166,171,173,178],{},[105,167,168],{},[48,169,170],{},"NUXT_PUBLIC_CONVEX_URL",[105,172,112],{},[105,174,175],{},[48,176,177],{},"http:\u002F\u002Flocalhost:3210",[105,179,180],{},"URL des Convex-Backends (Browser → Convex).",[84,182,183,188,190,195],{},[105,184,185],{},[48,186,187],{},"NUXT_PUBLIC_CONVEX_SITE_URL",[105,189,112],{},[105,191,192],{},[48,193,194],{},"http:\u002F\u002Flocalhost:3211",[105,196,197],{},"URL des Convex-Site-Proxys (Browser → HTTP-Actions).",[84,199,200,205,207,212],{},[105,201,202],{},[48,203,204],{},"NUXT_PUBLIC_SITE_URL",[105,206,112],{},[105,208,209],{},[48,210,211],{},"http:\u002F\u002Flocalhost:3000",[105,213,214],{},"URL der Webanwendung.",[73,216,218],{"id":217},"mta-konfiguration","MTA-Konfiguration",[26,220,223],{"title":221,"type":222},"Der MTA ist ein optionaler Service","info",[11,224,225,226,229,230,233,234,237,238,241,242,245,246,248,249,19],{},"Der eingebaute MTA läuft nur, wenn er der Zustell-Provider ist (",[48,227,228],{},"EMAIL_PROVIDER=mta",") oder wenn ",[48,231,232],{},"postbox","\u002F",[48,235,236],{},"inbox"," ihn für eingehende Mail benötigen — gesteuert über das Docker-Compose-Profil ",[48,239,240],{},"mta",". Der Standard-Self-Host liefert ",[48,243,244],{},"COMPOSE_PROFILES=mta"," aus; ein Deployment mit Resend\u002FSES, ein reines Empfangs- oder ein reines IMAP-Deployment lässt ",[48,247,240],{}," weg und betreibt ihn nicht. Diese Variablen gelten nur, wenn der MTA aktiv ist. Siehe ",[15,250,252],{"href":251},"\u002Fguide\u002Foperating-modes","Betriebsmodi",[78,254,255,267],{},[81,256,257],{},[84,258,259,261,263,265],{},[87,260,89],{},[87,262,92],{},[87,264,95],{},[87,266,98],{},[100,268,269,286,302,320,335,349,366,389,409,426,442,463,480],{},[84,270,271,276,278,280],{},[105,272,273],{},[48,274,275],{},"MTA_API_KEY",[105,277,112],{},[105,279,115],{},[105,281,282,283,122],{},"Gemeinsames Secret für die Authentifizierung Convex → MTA. Mit ",[48,284,285],{},"openssl rand -base64 32",[84,287,288,293,295,297],{},[105,289,290],{},[48,291,292],{},"MTA_WEBHOOK_SECRET",[105,294,112],{},[105,296,115],{},[105,298,299,300,122],{},"HMAC-Secret für Webhook-Callbacks MTA → Convex. Mit ",[48,301,285],{},[84,303,304,309,312,317],{},[105,305,306],{},[48,307,308],{},"EHLO_HOSTNAME",[105,310,311],{},"Für Zustellung",[105,313,314],{},[48,315,316],{},"mail.localhost",[105,318,319],{},"Hostname für SMTP EHLO\u002FHELO. Der Platzhalter lässt den Service starten, dessen IP bleibt jedoch in Quarantäne, bis der Hostname zu einem Forward-Confirmed PTR passt.",[84,321,322,327,330,332],{},[105,323,324],{},[48,325,326],{},"EHLO_HOSTNAMES",[105,328,329],{},"Nein",[105,331,115],{},[105,333,334],{},"JSON-Zuordnung von Versand-IP zu EHLO-Hostname für Deployments mit mehreren IPs.",[84,336,337,342,344,346],{},[105,338,339],{},[48,340,341],{},"MTA_GENERIC_PTR_SUFFIXES",[105,343,329],{},[105,345,115],{},[105,347,348],{},"Zusätzliche, kommagetrennte Provider-Standard-PTR-Suffixe, die als reputationsschwach markiert werden sollen.",[84,350,351,356,358,363],{},[105,352,353],{},[48,354,355],{},"MTA_ALLOW_UNVERIFIED_FCRDNS",[105,357,329],{},[105,359,360],{},[48,361,362],{},"false",[105,364,365],{},"Nur für Laborumgebungen: Umgehung der FCrDNS-Quarantäne. Niemals für die Zustellung ins Internet aktivieren.",[84,367,368,373,375,379],{},[105,369,370],{},[48,371,372],{},"MTA_IPV6_ENABLED",[105,374,329],{},[105,376,377],{},[48,378,362],{},[105,380,381,382,384,385,388],{},"Ausdrückliche Freigabe für ausgehendes IPv6. Solange ",[48,383,362],{},", werden IPv6-Pool-Einträge abgelehnt; bei ",[48,386,387],{},"true"," bleiben sie an IPv4-Identität, PTR\u002FAAAA und die SPF-Bereitschaft des Return-Path gebunden.",[84,390,391,396,398,403],{},[105,392,393],{},[48,394,395],{},"RETURN_PATH_DOMAIN",[105,397,311],{},[105,399,400],{},[48,401,402],{},"bounces.localhost",[105,404,405,406,408],{},"Domain für VERP-Return-Path-Adressen bei Bounces. Der Standard ",[48,407,402],{}," startet problemlos; für den produktiven Versand erforderlich, dort mit einem MX-Record auf Ihren Server.",[84,410,411,416,418,423],{},[105,412,413],{},[48,414,415],{},"IP_POOLS_TRANSACTIONAL",[105,417,329],{},[105,419,420],{},[48,421,422],{},"127.0.0.1",[105,424,425],{},"Kommagetrennte IPs für die Zustellung transaktionaler E-Mails.",[84,427,428,433,435,439],{},[105,429,430],{},[48,431,432],{},"IP_POOLS_CAMPAIGN",[105,434,329],{},[105,436,437],{},[48,438,422],{},[105,440,441],{},"Kommagetrennte IPs für die Zustellung von Kampagnen-\u002FMarketing-E-Mails.",[84,443,444,449,451,456],{},[105,445,446],{},[48,447,448],{},"DKIM_KEYS",[105,450,329],{},[105,452,453],{},[48,454,455],{},"{}",[105,457,458,459,19],{},"DKIM-Signaturschlüssel als JSON. Siehe ",[15,460,462],{"href":461},"\u002Fdeveloper\u002Fself-hosting-dns-email#dkim","DNS- & E-Mail-Setup",[84,464,465,470,472,477],{},[105,466,467],{},[48,468,469],{},"WORKER_CONCURRENCY",[105,471,329],{},[105,473,474],{},[48,475,476],{},"50",[105,478,479],{},"Anzahl paralleler MTA-Worker-Threads.",[84,481,482,487,489,493],{},[105,483,484],{},[48,485,486],{},"MTA_LOG_LEVEL",[105,488,329],{},[105,490,491],{},[48,492,222],{},[105,494,495,496,499,500,499,502,499,505,19],{},"Log-Ausführlichkeit des MTA: ",[48,497,498],{},"debug",", ",[48,501,222],{},[48,503,504],{},"warn",[48,506,507],{},"error",[73,509,511],{"id":510},"port-überschreibungen","Port-Überschreibungen",[11,513,514],{},"Alle Ports lassen sich ändern, falls die Standardwerte mit vorhandenen Services kollidieren.",[78,516,517,528],{},[81,518,519],{},[84,520,521,523,525],{},[87,522,89],{},[87,524,95],{},[87,526,527],{},"Service",[100,529,530,545,560,579,594,609],{},[84,531,532,537,542],{},[105,533,534],{},[48,535,536],{},"CONVEX_PORT",[105,538,539],{},[48,540,541],{},"3210",[105,543,544],{},"Convex-Backend-API",[84,546,547,552,557],{},[105,548,549],{},[48,550,551],{},"CONVEX_SITE_PORT",[105,553,554],{},[48,555,556],{},"3211",[105,558,559],{},"Convex-HTTP-Actions",[84,561,562,567,572],{},[105,563,564],{},[48,565,566],{},"DASHBOARD_PORT",[105,568,569],{},[48,570,571],{},"6791",[105,573,574,575,578],{},"Convex-Dashboard (erfordert ",[48,576,577],{},"--profile dashboard","; nur an 127.0.0.1 gebunden — Zugriff über SSH-Tunnel)",[84,580,581,586,591],{},[105,582,583],{},[48,584,585],{},"WEB_PORT",[105,587,588],{},[48,589,590],{},"3000",[105,592,593],{},"Webanwendung",[84,595,596,601,606],{},[105,597,598],{},[48,599,600],{},"MTA_HTTP_PORT",[105,602,603],{},[48,604,605],{},"3100",[105,607,608],{},"MTA-HTTP-API",[84,610,611,616,621],{},[105,612,613],{},[48,614,615],{},"MTA_SMTP_PORT",[105,617,618],{},[48,619,620],{},"25",[105,622,623],{},"MTA-SMTP (Bounce-Verarbeitung)",[11,625,626,627,629,630,633,634,636,637,640],{},"Die Ports von Convex, MTA-HTTP und Dashboard binden standardmäßig nur an localhost (",[48,628,422],{},"). ",[48,631,632],{},"CONVEX_BIND"," (Standard ",[48,635,422],{},") legt fest, an welches Interface das Convex-Backend bindet, und ",[48,638,639],{},"REDIS_PASSWORD"," setzt das Redis-Authentifizierungspasswort.",[11,642,643,644,647,648,499,651,654,655,233,658,661,662,664,665,669],{},"Redis und ClamAV veröffentlichen ",[34,645,646],{},"keinen Host-Port"," — sie sind ausschließlich über das interne Docker-Netzwerk erreichbar (",[48,649,650],{},"redis:6379",[48,652,653],{},"clamav:3310","); es gibt daher keinen Schalter ",[48,656,657],{},"REDIS_PORT",[48,659,660],{},"CLAMAV_PORT"," zur Host-Überschreibung. (",[48,663,660],{}," wird am MTA-Container als die ",[666,667,668],"em",{},"interne"," Adresse gesetzt, die dessen Scan-Client anspricht; ein Host-Port wird damit nicht gemappt.)",[73,671,673],{"id":672},"analytics-optional","Analytics (optional)",[78,675,676,686],{},[81,677,678],{},[84,679,680,682,684],{},[87,681,89],{},[87,683,95],{},[87,685,98],{},[100,687,688,700],{},[84,689,690,695,697],{},[105,691,692],{},[48,693,694],{},"NUXT_PUBLIC_POSTHOG_API_KEY",[105,696,115],{},[105,698,699],{},"PostHog-Projekt-API-Key für clientseitiges Tracking.",[84,701,702,707,712],{},[105,703,704],{},[48,705,706],{},"NUXT_PUBLIC_POSTHOG_HOST",[105,708,709],{},[48,710,711],{},"https:\u002F\u002Feu.i.posthog.com",[105,713,714],{},"URL der PostHog-Instanz.",[73,716,718],{"id":717},"deployment-modus","Deployment-Modus",[11,720,721],{},"Diese Variablen steuern, welche Oberfläche die Web-App anzeigt und ob In-App-Updates ausgeführt werden können. Die Standardwerte passen zu einer selbst gehosteten Installation — Sie müssen sie selten ändern.",[78,723,724,734],{},[81,725,726],{},[84,727,728,730,732],{},[87,729,89],{},[87,731,95],{},[87,733,98],{},[100,735,736,758],{},[84,737,738,743,748],{},[105,739,740],{},[48,741,742],{},"OWLAT_DEPLOYMENT_MODE",[105,744,745],{},[48,746,747],{},"selfhost",[105,749,750,751,754,755,757],{},"Wird von der Web-App gelesen (",[48,752,753],{},"config.public.deploymentMode","). Steuert das Onboarding-Banner für Self-Hosting. Für ein OSS-Deployment auf ",[48,756,747],{}," belassen.",[84,759,760,765,770],{},[105,761,762],{},[48,763,764],{},"OWLAT_INSTALL_DIR",[105,766,767],{},[48,768,769],{},".\u002F",[105,771,772,773,776,777,780],{},"Absoluter Pfad zu diesem Repository auf dem Host. Der ",[48,774,775],{},"updater","-Sidecar bindet ihn ein, um Compose-Templates zu schreiben und ",[48,778,779],{},"docker compose pull && up -d"," auszuführen. Für In-App-Updates erforderlich.",[26,782,784],{"title":783,"type":222},"OWLAT_HOSTED_MODE ist im OSS-Repo wirkungslos",[11,785,786,787,790,791,794,795,499,797,800],{},"Das ",[48,788,789],{},"owlat","-Setup-CLI schreibt einen Wert für ",[48,792,793],{},"OWLAT_HOSTED_MODE"," in die ",[48,796,50],{},[34,798,799],{},"kein Service in diesem OSS-Repository liest ihn jedoch"," — die Control Plane der gehosteten Cloud (und deren Abrechnung) wurde in ein separates, privates Repository ausgelagert. Ihn zu setzen hat auf eine selbst gehostete Instanz keine Auswirkung.",[73,802,804],{"id":803},"image-pinning-optional","Image-Pinning (optional)",[11,806,807,808,811,812,815],{},"Die Compose-Datei pinnt Upstream-Images über eigene ",[48,809,810],{},"*_VERSION","-Variablen auf Minor-Versionen, jeweils mit einem fest hinterlegten Standardwert. Überschreiben Sie sie nur, um eine andere Version zu pinnen; die Compose-Dateien produktiver Releases fixieren diese zusätzlich auf ",[48,813,814],{},"@sha256","-Digests.",[78,817,818,829],{},[81,819,820],{},[84,821,822,824,826],{},[87,823,89],{},[87,825,95],{},[87,827,828],{},"Image",[100,830,831,848,864,881,898],{},[84,832,833,838,843],{},[105,834,835],{},[48,836,837],{},"CONVEX_BACKEND_VERSION",[105,839,840],{},[48,841,842],{},"latest",[105,844,845],{},[48,846,847],{},"ghcr.io\u002Fget-convex\u002Fconvex-backend",[84,849,850,855,859],{},[105,851,852],{},[48,853,854],{},"CONVEX_DASHBOARD_VERSION",[105,856,857],{},[48,858,842],{},[105,860,861],{},[48,862,863],{},"ghcr.io\u002Fget-convex\u002Fconvex-dashboard",[84,865,866,871,876],{},[105,867,868],{},[48,869,870],{},"REDIS_VERSION",[105,872,873],{},[48,874,875],{},"7.4-alpine",[105,877,878],{},[48,879,880],{},"redis",[84,882,883,888,893],{},[105,884,885],{},[48,886,887],{},"CLAMAV_VERSION",[105,889,890],{},[48,891,892],{},"stable",[105,894,895],{},[48,896,897],{},"clamav\u002Fclamav",[84,899,900,905,910],{},[105,901,902],{},[48,903,904],{},"CADDY_VERSION",[105,906,907],{},[48,908,909],{},"2.8-alpine",[105,911,912,915,916,919],{},[48,913,914],{},"caddy"," (nur mit ",[48,917,918],{},"--profile tls"," verwendet)",[11,921,922,923,499,926,499,928,499,930,499,933,936,937,940,941,943,944,947,948,499,950,953,954,957],{},"Die eigenen Images von Owlat (",[48,924,925],{},"web",[48,927,240],{},[48,929,775],{},[48,931,932],{},"convex-deploy",[48,934,935],{},"code-worker",") werden mit ",[48,938,939],{},"OWLAT_VERSION"," getaggt — der Tag für den Image-Pull ist standardmäßig ",[48,942,842],{},", während das Build-Argument im Container standardmäßig auf dem Sentinel ",[48,945,946],{},"dev"," für lokale Builds steht. Die Release-Pipeline schreibt den gepinnten Tag; bearbeiten Sie ",[48,949,939],{},[48,951,952],{},"OWLAT_GIT_SHA"," oder ",[48,955,956],{},"OWLAT_BUILD_DATE"," daher nicht von Hand.",[21,959,56],{"id":960},"convex-umgebungsvariablen",[11,962,963],{},"Diese werden nach dem Deployen der Functions gesetzt. Sie steuern das Verhalten auf Anwendungsebene innerhalb des Convex-Backends.",[965,966,971],"pre",{"className":967,"code":968,"language":969,"meta":970,"style":970},"language-bash shiki shiki-themes github-light github-dark-dimmed","npx convex env set VAR_NAME \"value\" \\\n  --url http:\u002F\u002Flocalhost:3210 \\\n  --admin-key \u003Cyour-admin-key>\n","bash","",[48,972,973,1002,1014],{"__ignoreMap":970},[974,975,978,982,986,989,992,995,998],"span",{"class":976,"line":977},"line",1,[974,979,981],{"class":980},"sOLd2","npx",[974,983,985],{"class":984},"s-HuK"," convex",[974,987,988],{"class":984}," env",[974,990,991],{"class":984}," set",[974,993,994],{"class":984}," VAR_NAME",[974,996,997],{"class":984}," \"value\"",[974,999,1001],{"class":1000},"s74oq"," \\\n",[974,1003,1005,1009,1012],{"class":976,"line":1004},2,[974,1006,1008],{"class":1007},"sviXB","  --url",[974,1010,1011],{"class":984}," http:\u002F\u002Flocalhost:3210",[974,1013,1001],{"class":1000},[974,1015,1017,1020,1024,1027,1031],{"class":976,"line":1016},3,[974,1018,1019],{"class":1007},"  --admin-key",[974,1021,1023],{"class":1022},"s7YZ4"," \u003C",[974,1025,1026],{"class":984},"your-admin-ke",[974,1028,1030],{"class":1029},"sYgZi","y",[974,1032,1033],{"class":1022},">\n",[73,1035,1037],{"id":1036},"diese-für-den-normalbetrieb-setzen","Diese für den Normalbetrieb setzen",[11,1039,1040],{},"Setzen Sie alle diese Variablen in jedem echten Deployment. Im Code werden die meisten mit sinnvollen Fallbacks gelesen und lassen eine Function nicht abstürzen, wenn sie fehlen — Auth-Weiterleitungen, Abmeldelinks und CORS sind ohne sie jedoch falsch.",[78,1042,1043,1051],{},[81,1044,1045],{},[84,1046,1047,1049],{},[87,1048,89],{},[87,1050,98],{},[100,1052,1053,1069,1081,1093],{},[84,1054,1055,1060],{},[105,1056,1057],{},[48,1058,1059],{},"SITE_URL",[105,1061,1062,1063,1065,1066,1068],{},"Öffentliche Site-URL für Auth-Weiterleitungen (z. B. ",[48,1064,211],{},"). Fällt auf ",[48,1067,211],{}," zurück.",[84,1070,1071,1076],{},[105,1072,1073],{},[48,1074,1075],{},"BETTER_AUTH_SECRET",[105,1077,1078,1079,122],{},"Secret zum Signieren von Auth-Sessions. Mit ",[48,1080,285],{},[84,1082,1083,1088],{},[105,1084,1085],{},[48,1086,1087],{},"UNSUBSCRIBE_SECRET",[105,1089,1090,1091,122],{},"HMAC-Secret für signierte Abmelde-Tokens. Mit ",[48,1092,285],{},[84,1094,1095,1100],{},[105,1096,1097],{},[48,1098,1099],{},"EMAIL_PROVIDER",[105,1101,1102,1103,499,1105,499,1108,499,1111,499,1114,953,1117,1120],{},"E-Mail-Provider: ",[48,1104,240],{},[48,1106,1107],{},"ses",[48,1109,1110],{},"resend",[48,1112,1113],{},"smtp",[48,1115,1116],{},"mandrill",[48,1118,1119],{},"emailit",". Kein impliziter Standardwert — bleibt die Variable ungesetzt, werden Sendungen abgelehnt statt an den eingebauten MTA geleitet.",[26,1122,1124],{"title":1123,"type":29},"CONVEX_SITE_URL nicht über `convex env set` setzen",[11,1125,1126,1129,1130,1133,1134,1137,1138,1141,1142,1145,1146,1149,1150,1152,1153,1155],{},[48,1127,1128],{},"CONVEX_SITE_URL"," (verwendet für Tracking-Pixel und Abmeldelinks) ist ein Convex-",[34,1131,1132],{},"Built-in"," — ",[48,1135,1136],{},"convex env set"," lehnt es mit ",[48,1139,1140],{},"EnvVarNameForbidden"," ab. Das Backend leitet den Wert von ",[48,1143,1144],{},"CONVEX_SITE_ORIGIN"," am ",[48,1147,1148],{},"convex","-Container ab, das docker-compose aus ",[48,1151,187],{}," in Ihrer ",[48,1154,50],{}," interpoliert. Setzen Sie die öffentliche URL dort, nicht als Umgebungsvariable einer Convex-Function.",[26,1157,1159],{"title":1158,"type":29},"Das einzige zwingend erforderliche Paar",[11,1160,1161,1164,1165,1167,1168,1171,1172,1175,1176,1179,1180,1182],{},[48,1162,1163],{},"MTA_API_URL"," und ",[48,1166,275],{}," sind die einzigen Variablen, die einen harten Fehler auslösen — und das nur, wenn tatsächlich eine E-Mail über den MTA-Provider versendet wird (Auth-Einladungen, Kampagnen, transaktionale Mail). Der Versand scheitert mit ",[48,1169,1170],{},"No system email transport configured",", wenn eine der beiden nicht gesetzt ist (",[48,1173,1174],{},"apps\u002Fapi\u002Fconvex\u002FsystemMail.ts","; der MTA-Provider selbst liegt in ",[48,1177,1178],{},"apps\u002Fapi\u002Fconvex\u002Flib\u002FsendProviders\u002Fmta\u002Findex.ts","). Setzen Sie beide immer dann, wenn ",[48,1181,228],{}," gilt.",[78,1184,1185,1193],{},[81,1186,1187],{},[84,1188,1189,1191],{},[87,1190,89],{},[87,1192,98],{},[100,1194,1195,1208,1223],{},[84,1196,1197,1201],{},[105,1198,1199],{},[48,1200,1163],{},[105,1202,1203,1204,1207],{},"URL des MTA-Service. Verwenden Sie ",[48,1205,1206],{},"http:\u002F\u002Fmta:3100"," für das Docker-Networking.",[84,1209,1210,1214],{},[105,1211,1212],{},[48,1213,275],{},[105,1215,1216,1217,1219,1220,1222],{},"Muss mit ",[48,1218,275],{}," in der Docker-",[48,1221,50],{}," übereinstimmen.",[84,1224,1225,1229],{},[105,1226,1227],{},[48,1228,292],{},[105,1230,1216,1231,1219,1233,1222],{},[48,1232,292],{},[48,1234,50],{},[73,1236,1238],{"id":1237},"absenderidentität","Absenderidentität",[78,1240,1241,1251],{},[81,1242,1243],{},[84,1244,1245,1247,1249],{},[87,1246,89],{},[87,1248,95],{},[87,1250,98],{},[100,1252,1253,1268,1283,1298],{},[84,1254,1255,1260,1265],{},[105,1256,1257],{},[48,1258,1259],{},"DEFAULT_FROM_EMAIL",[105,1261,1262],{},[48,1263,1264],{},"noreply@example.com",[105,1266,1267],{},"Standard-Absenderadresse.",[84,1269,1270,1275,1280],{},[105,1271,1272],{},[48,1273,1274],{},"DEFAULT_FROM_NAME",[105,1276,1277],{},[48,1278,1279],{},"Owlat",[105,1281,1282],{},"Standardmäßig angezeigter Absendername.",[84,1284,1285,1290,1295],{},[105,1286,1287],{},[48,1288,1289],{},"DEFAULT_FROM_DOMAIN",[105,1291,1292],{},[48,1293,1294],{},"mail.owlat.app",[105,1296,1297],{},"Domain für System-E-Mails (Einladungen usw.).",[84,1299,1300,1305,1307],{},[105,1301,1302],{},[48,1303,1304],{},"ALLOWED_ORIGINS",[105,1306,115],{},[105,1308,1309,1310,1313],{},"Kommagetrennte CORS-Origins (z. B. ",[48,1311,1312],{},"http:\u002F\u002Flocalhost:3000,http:\u002F\u002Flocalhost:3001",").",[73,1315,1317],{"id":1316},"llm-provider-optional","LLM-Provider (optional)",[11,1319,1320,1321,1325],{},"Owlat spricht mit einem einzigen austauschbaren LLM-Provider (",[15,1322,1324],{"href":1323},"\u002Fdeveloper\u002Fdecisions\u002F007-pluggable-llm","ADR-007","). Dieselbe Konfiguration versorgt KI-Agentenantworten, Übersetzungen, Embeddings für den Knowledge Graph und den Visualisierungs-Agenten. Alles, was das Format der OpenAI Chat Completions \u002F Embeddings spricht, funktioniert (OpenAI, OpenRouter, Ollama, lokales vLLM\u002FLM Studio). Setzen Sie diese Variablen nur, wenn Sie ein KI-Feature-Flag aktivieren.",[78,1327,1328,1338],{},[81,1329,1330],{},[84,1331,1332,1334,1336],{},[87,1333,89],{},[87,1335,95],{},[87,1337,98],{},[100,1339,1340,1363,1378,1391,1406,1421],{},[84,1341,1342,1347,1352],{},[105,1343,1344],{},[48,1345,1346],{},"LLM_PROVIDER",[105,1348,1349],{},[48,1350,1351],{},"openai",[105,1353,1354,499,1356,953,1359,1362],{},[48,1355,1351],{},[48,1357,1358],{},"openrouter",[48,1360,1361],{},"ollama",". Wählt den Client und eine Standard-Basis-URL.",[84,1364,1365,1370,1372],{},[105,1366,1367],{},[48,1368,1369],{},"LLM_API_KEY",[105,1371,115],{},[105,1373,1374,1375,1377],{},"API-Key des Providers. Für ",[48,1376,1361],{}," nicht erforderlich.",[84,1379,1380,1385,1388],{},[105,1381,1382],{},[48,1383,1384],{},"LLM_BASE_URL",[105,1386,1387],{},"Provider-Standard",[105,1389,1390],{},"Überschreibt den Endpunkt (für selbst gehostete\u002Flokale Server). OpenRouter und Ollama erhalten automatisch sinnvolle Standardwerte.",[84,1392,1393,1398,1403],{},[105,1394,1395],{},[48,1396,1397],{},"LLM_MODEL_FAST",[105,1399,1400],{},[48,1401,1402],{},"gpt-4o-mini",[105,1404,1405],{},"Modell für schnelle Aufgaben (Klassifizieren\u002FExtrahieren\u002FAbsichern\u002FZusammenfassen).",[84,1407,1408,1413,1418],{},[105,1409,1410],{},[48,1411,1412],{},"LLM_MODEL_CAPABLE",[105,1414,1415],{},[48,1416,1417],{},"gpt-4o",[105,1419,1420],{},"Modell für anspruchsvolle Aufgaben (Entwurf).",[84,1422,1423,1428,1433],{},[105,1424,1425],{},[48,1426,1427],{},"LLM_EMBEDDING_MODEL",[105,1429,1430],{},[48,1431,1432],{},"text-embedding-3-small",[105,1434,1435],{},"Embedding-Modell für den Knowledge Graph.",[26,1437,1439],{"title":1438,"type":222},"Abwärtskompatible Key-Aliase",[11,1440,1441,1164,1444,1447,1448,1450,1451,1453,1454,1453,1456,1458,1459,1461,1462,1313],{},[48,1442,1443],{},"OPENAI_API_KEY",[48,1445,1446],{},"OPENROUTER_API_KEY"," werden als Fallback-Aliase für ",[48,1449,1369],{}," akzeptiert (Reihenfolge: ",[48,1452,1369],{}," → ",[48,1455,1446],{},[48,1457,1443],{},"). Bevorzugen Sie bei neuen Installationen ",[48,1460,1369],{}," (",[48,1463,1464],{},"apps\u002Fapi\u002Fconvex\u002Flib\u002FllmProvider.ts",[26,1466,1468],{"title":1467,"type":222},"Claude-Modelle betreiben",[11,1469,1470,1472,1473,499,1475,1164,1477,1479,1480,1483,1484,1486,1487,1489,1490,1492],{},[48,1471,1346],{}," akzeptiert nur ",[48,1474,1351],{},[48,1476,1358],{},[48,1478,1361],{},". Um Claude-Modelle zu betreiben, nutzen Sie den OpenAI-kompatiblen Weg: Setzen Sie ",[48,1481,1482],{},"LLM_PROVIDER=openai"," (oder belassen Sie den Standard), richten Sie ",[48,1485,1384],{}," auf einen OpenAI-kompatiblen Endpunkt und setzen Sie ",[48,1488,1412],{}," \u002F ",[48,1491,1397],{}," auf die Claude-Modell-IDs.",[73,1494,1496],{"id":1495},"weitere-integrationen-optional","Weitere Integrationen (optional)",[78,1498,1499,1507],{},[81,1500,1501],{},[84,1502,1503,1505],{},[87,1504,89],{},[87,1506,98],{},[100,1508,1509,1519,1534,1548,1558,1568],{},[84,1510,1511,1516],{},[105,1512,1513],{},[48,1514,1515],{},"GOOGLE_SAFE_BROWSING_API_KEY",[105,1517,1518],{},"Key für die Google-Safe-Browsing-API v4 zur Prüfung der URL-Reputation.",[84,1520,1521,1526],{},[105,1522,1523],{},[48,1524,1525],{},"MTA_INTERNAL_URL",[105,1527,1528,1529,1531,1532,19],{},"Bevorzugte clusterinterne MTA-Basis-URL für alle HTTP-Aufrufe Convex→MTA (ausgehender Versand, Cache-Push, Zustell-Hooks, Anhangsprüfung); überschreibt das öffentliche ",[48,1530,1163],{},". Z. B. ",[48,1533,1206],{},[84,1535,1536,1541],{},[105,1537,1538],{},[48,1539,1540],{},"MAIL_SYNC_API_URL",[105,1542,1543,1544,1547],{},"URL des Mail-Sync-Workers für externe IMAP-\u002FSMTP-Konten. Ohne sie wird ein ausgehender externer Versand für jeden Empfänger als fehlgeschlagen markiert (errorCode ",[48,1545,1546],{},"EXTERNAL_NOT_CONFIGURED","), statt zugestellt zu werden.",[84,1549,1550,1555],{},[105,1551,1552],{},[48,1553,1554],{},"MAIL_SYNC_API_KEY",[105,1556,1557],{},"Gemeinsames Secret für den Mail-Sync-Worker.",[84,1559,1560,1565],{},[105,1561,1562],{},[48,1563,1564],{},"POSTHOG_API_KEY",[105,1566,1567],{},"PostHog-API-Key für serverseitige Analytics.",[84,1569,1570,1575],{},[105,1571,1572],{},[48,1573,1574],{},"POSTHOG_HOST",[105,1576,1577,1578,1313],{},"URL der PostHog-Instanz (Standard: ",[48,1579,711],{},[11,1581,1582,1583,19],{},"Die vollständige Variablenreferenz einschließlich AWS SES, Resend und Webhooks für eingehende Kanäle finden Sie unter ",[15,1584,1586],{"href":1585},"\u002Fdeveloper\u002Fenvironment-variables","Umgebungsvariablen",[21,1588,1590],{"id":1589},"service-topologie","Service-Topologie",[78,1592,1593,1608],{},[81,1594,1595],{},[84,1596,1597,1599,1602,1605],{},[87,1598,527],{},[87,1600,1601],{},"Ports",[87,1603,1604],{},"Hängt ab von",[87,1606,1607],{},"Healthcheck",[100,1609,1610,1627,1651,1663,1677,1694,1715,1729,1745,1762,1781,1799,1815],{},[84,1611,1612,1616,1619,1621],{},[105,1613,1614],{},[34,1615,1148],{},[105,1617,1618],{},"3210 (API), 3211 (Site-Proxy)",[105,1620,115],{},[105,1622,1623,1626],{},[48,1624,1625],{},"curl -f http:\u002F\u002Flocalhost:3210\u002Fversion"," alle 15 s",[84,1628,1629,1634,1637,1640],{},[105,1630,1631],{},[34,1632,1633],{},"convex-dashboard",[105,1635,1636],{},"6791 (nur 127.0.0.1)",[105,1638,1639],{},"convex (healthy)",[105,1641,1642,1643,1646,1647,1650],{},"— (Profil ",[48,1644,1645],{},"dashboard","; Zugriff über SSH-Tunnel ",[48,1648,1649],{},"ssh -L 6791:127.0.0.1:6791 host",")",[84,1652,1653,1657,1659,1661],{},[105,1654,1655],{},[34,1656,925],{},[105,1658,590],{},[105,1660,1639],{},[105,1662,115],{},[84,1664,1665,1669,1672,1675],{},[105,1666,1667],{},[34,1668,240],{},[105,1670,1671],{},"3100 (HTTP), 25 (SMTP)",[105,1673,1674],{},"redis (healthy), convex (healthy), clamav (gestartet, optional)",[105,1676,115],{},[84,1678,1679,1683,1686,1688],{},[105,1680,1681],{},[34,1682,880],{},[105,1684,1685],{},"6379",[105,1687,115],{},[105,1689,1690,1693],{},[48,1691,1692],{},"redis-cli ping"," alle 10 s",[84,1695,1696,1701,1704,1706],{},[105,1697,1698],{},[34,1699,1700],{},"clamav",[105,1702,1703],{},"3310",[105,1705,115],{},[105,1707,1708,1711,1712,1714],{},[48,1709,1710],{},"clamdcheck"," alle 60 s (600 s Startverzögerung) (Profil ",[48,1713,1700],{},"; aus, sofern die Dateiprüfung nicht aktiviert ist)",[84,1716,1717,1721,1724,1727],{},[105,1718,1719],{},[34,1720,775],{},[105,1722,1723],{},"3200 (nur intern)",[105,1725,1726],{},"docker-socket-proxy",[105,1728,115],{},[84,1730,1731,1735,1737,1739],{},[105,1732,1733],{},[34,1734,932],{},[105,1736,115],{},[105,1738,1639],{},[105,1740,1741,1742,1650],{},"Einmalig (Profil ",[48,1743,1744],{},"deploy",[84,1746,1747,1751,1754,1757],{},[105,1748,1749],{},[34,1750,914],{},[105,1752,1753],{},"80, 443",[105,1755,1756],{},"web, convex, mta",[105,1758,1642,1759,1650],{},[48,1760,1761],{},"tls",[84,1763,1764,1768,1771,1773],{},[105,1765,1766],{},[34,1767,935],{},[105,1769,1770],{},"— (nur intern)",[105,1772,1639],{},[105,1774,1642,1775,1778,1779,1650],{},[48,1776,1777],{},"inbox-codetasks","; außerdem ",[48,1780,946],{},[84,1782,1783,1788,1791,1794],{},[105,1784,1785],{},[34,1786,1787],{},"imap",[105,1789,1790],{},"993",[105,1792,1793],{},"convex (healthy), imap-cert-init (abgeschlossen)",[105,1795,1642,1796,1650],{},[48,1797,1798],{},"personal-mail",[84,1800,1801,1806,1808,1810],{},[105,1802,1803],{},[34,1804,1805],{},"mail-sync",[105,1807,1770],{},[105,1809,1639],{},[105,1811,1642,1812,1650],{},[48,1813,1814],{},"external-mail",[84,1816,1817,1821,1823,1825],{},[105,1818,1819],{},[34,1820,1361],{},[105,1822,1770],{},[105,1824,115],{},[105,1826,1827,1828,1489,1831,1650],{},"— (Profile ",[48,1829,1830],{},"ai",[48,1832,946],{},[11,1834,1835,1836,1838,1839,1842,1843,1845,1846,1848,1849,1852],{},"Der ",[34,1837,775],{},"-Sidecar hat keinen öffentlichen Port — die Web-App erreicht ihn über das Docker-Netzwerk unter ",[48,1840,1841],{},"http:\u002F\u002Fupdater:3200",". Er bindet ausschließlich ",[48,1844,764],{}," mit Schreibrechten ein, um ein neues Compose-Template schreiben zu können, und erreicht die Docker-API über den Least-Privilege-Sidecar ",[48,1847,1726],{}," (der den Socket schreibgeschützt einbindet) via ",[48,1850,1851],{},"DOCKER_HOST=tcp:\u002F\u002Fdocker-socket-proxy:2375"," — den Docker-Socket bindet er nicht mehr direkt ein.",[11,1854,1855,1856,1461,1858,1860,1861,499,1863,1164,1865,1867,1868,1871],{},"Der optionale Service ",[34,1857,914],{},[48,1859,918],{},") ist ein Reverse Proxy, der TLS über Let's Encrypt terminiert und ",[48,1862,925],{},[48,1864,1148],{},[48,1866,240],{}," auf Subdomains vorschaltet. Passen Sie die ",[48,1869,1870],{},"Caddyfile"," vor dem Start an Ihre Domains an, oder stellen Sie dem Stack stattdessen Ihren eigenen Reverse Proxy voran.",[11,1873,1874,1875,1461,1877,1880,1881,1884,1885,1164,1888,1891],{},"Der Sidecar ",[34,1876,935],{},[48,1878,1879],{},"--profile inbox-codetasks",", ebenfalls über ",[48,1882,1883],{},"--profile dev"," verfügbar) ist der KI-Coding-Agent, der Code-Tasks übernimmt. Er liest die Variablen ",[48,1886,1887],{},"LLM_*",[48,1889,1890],{},"GITHUB_*"," und ist standardmäßig aus.",[21,1893,1895],{"id":1894},"volumes","Volumes",[78,1897,1898,1911],{},[81,1899,1900],{},[84,1901,1902,1905,1908],{},[87,1903,1904],{},"Volume",[87,1906,1907],{},"Persistiert",[87,1909,1910],{},"Backup-Priorität",[100,1912,1913,1929,1942,1955,1973,1990,2005],{},[84,1914,1915,1920,1923],{},[105,1916,1917],{},[48,1918,1919],{},"convex-data",[105,1921,1922],{},"Datenbank, Dateispeicher, Vektorindizes",[105,1924,1925,1928],{},[34,1926,1927],{},"Kritisch"," — sämtliche Anwendungsdaten",[84,1930,1931,1936,1939],{},[105,1932,1933],{},[48,1934,1935],{},"redis-data",[105,1937,1938],{},"MTA-Job-Queue (AOF)",[105,1940,1941],{},"Mittel — laufende E-Mail-Jobs",[84,1943,1944,1949,1952],{},[105,1945,1946],{},[48,1947,1948],{},"clamav-data",[105,1950,1951],{},"Virensignaturen",[105,1953,1954],{},"Niedrig — werden automatisch neu heruntergeladen",[84,1956,1957,1965,1970],{},[105,1958,1959,1489,1962],{},[48,1960,1961],{},"caddy-data",[48,1963,1964],{},"caddy-config",[105,1966,1967,1968,1650],{},"TLS-Zertifikate und Caddy-Zustand (nur mit ",[48,1969,918],{},[105,1971,1972],{},"Niedrig — Zertifikate werden automatisch neu ausgestellt",[84,1974,1975,1980,1987],{},[105,1976,1977],{},[48,1978,1979],{},"code-workspace",[105,1981,1982,1983,953,1985,1650],{},"Checkout des Code-Workers (nur mit ",[48,1984,1879],{},[48,1986,1883],{},[105,1988,1989],{},"Niedrig — kurzlebiger Arbeitsbaum",[84,1991,1992,1997,2003],{},[105,1993,1994],{},[48,1995,1996],{},"mail-certs",[105,1998,1999,2000,1650],{},"TLS-Zertifikate des IMAP-Servers (nur mit ",[48,2001,2002],{},"--profile personal-mail",[105,2004,1972],{},[84,2006,2007,2012,2020],{},[105,2008,2009],{},[48,2010,2011],{},"ollama-data",[105,2013,2014,2015,1489,2018,1650],{},"Ollama-Modelldateien (nur mit ",[48,2016,2017],{},"--profile ai",[48,2019,1883],{},[105,2021,2022],{},"Niedrig — Modelle werden automatisch neu heruntergeladen",[2024,2025,2026],"style",{},"html pre.shiki code .sOLd2, html code.shiki .sOLd2{--shiki-default:#6F42C1;--shiki-dark:#F69D50}html pre.shiki code .s-HuK, html code.shiki .s-HuK{--shiki-default:#032F62;--shiki-dark:#96D0FF}html pre.shiki code .s74oq, html code.shiki .s74oq{--shiki-default:#005CC5;--shiki-dark:#F47067}html pre.shiki code .sviXB, html code.shiki .sviXB{--shiki-default:#005CC5;--shiki-dark:#6CB6FF}html pre.shiki code .s7YZ4, html code.shiki .s7YZ4{--shiki-default:#D73A49;--shiki-dark:#F47067}html pre.shiki code .sYgZi, html code.shiki .sYgZi{--shiki-default:#24292E;--shiki-dark:#ADBAC7}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":970,"searchDepth":1004,"depth":1004,"links":2028},[2029,2030,2039,2045,2046],{"id":23,"depth":1004,"text":24},{"id":64,"depth":1004,"text":65,"children":2031},[2032,2033,2034,2035,2036,2037,2038],{"id":75,"depth":1016,"text":76},{"id":143,"depth":1016,"text":144},{"id":217,"depth":1016,"text":218},{"id":510,"depth":1016,"text":511},{"id":672,"depth":1016,"text":673},{"id":717,"depth":1016,"text":718},{"id":803,"depth":1016,"text":804},{"id":960,"depth":1004,"text":56,"children":2040},[2041,2042,2043,2044],{"id":1036,"depth":1016,"text":1037},{"id":1237,"depth":1016,"text":1238},{"id":1316,"depth":1016,"text":1317},{"id":1495,"depth":1016,"text":1496},{"id":1589,"depth":1004,"text":1590},{"id":1894,"depth":1004,"text":1895},"Vollständige Referenz für Docker-Umgebungsvariablen, Convex-Backend-Variablen, Service-Topologie und Persistenz von Volumes.","md",{},true,"\u002Fdeveloper\u002Fself-hosting-config",{"title":6,"description":2047},"3.developer\u002F31.self-hosting-config","WvedVfmhfDiCpqHnRvA18T5nY4N3BIViOCM2UR-G0_Y",[2056,2058],{"title":18,"path":17,"stem":2057,"children":-1},"3.developer\u002F30.self-hosting",{"title":462,"path":2059,"stem":2060,"children":-1},"\u002Fdeveloper\u002Fself-hosting-dns-email","3.developer\u002F32.self-hosting-dns-email",1786915109869]