# AeroMC – CurseForge-Weiterleitung Kleiner Dienst, der den CurseForge-API-Schlüssel hält und die Anfragen stellvertretend für den Launcher stellt. ## Wozu das Ganze CurseForge erlaubt es nicht, den API-Schlüssel weiterzugeben. In einer verteilten `.exe` wäre er für jeden auslesbar – das Entpacken einer Electron-Anwendung dauert keine Minute. Deshalb bleibt der Schlüssel hier auf dem Server, und der Launcher kennt nur die Adresse dieses Dienstes. ## Wege | Weg | Zweck | |---|---| | `GET /health` | Lebenszeichen, verrät nichts über den Schlüssel | | `POST /v1/mods/files` | Dateiliste auflösen, Rumpf `{ "fileIds": [...] }`, höchstens 100 je Anfrage | | `GET /v1/download?url=…` | Mod-Datei durchreichen; das CurseForge-CDN verlangt seit Juli 2026 ebenfalls einen Schlüssel | ## Einrichten ```bash cp .env.example .env # CF_API_KEY eintragen ``` ### Ohne Docker Braucht nur Node 18 oder neuer, keine Pakete. ```bash node index.js ``` Dauerhaft über systemd: `aeromc-cf-proxy.service` nach `/etc/systemd/system/` kopieren, Pfade und Benutzer darin anpassen, dann ```bash systemctl daemon-reload systemctl enable --now aeromc-cf-proxy ``` ### Mit pm2 `ecosystem.config.js` liegt bei und liest die `.env` selbst ein – pm2 tut das von sich aus nämlich nicht. ```bash pm2 start ecosystem.config.js pm2 save pm2 startup # einmalig, für den Start nach einem Neustart ``` Nach jeder Änderung an der `.env`: ```bash pm2 restart aeromc-cf-proxy --update-env ``` Ohne `--update-env` behält pm2 die alten Werte, und du suchst lange nach dem Grund, warum der neue Schlüssel nicht greift. Nachsehen, ob er läuft: ```bash pm2 logs aeromc-cf-proxy --lines 20 ``` **Nicht auf Cluster-Betrieb umstellen.** Die Konfiguration steht bewusst auf `exec_mode: 'fork'` mit einem Prozess. Die Ratenbegrenzung zählt im Arbeitsspeicher – bei vier Arbeitern hätte jeder seine eigene Zählung, und die Grenze wäre in Wahrheit viermal so hoch wie eingestellt. ### Mit Docker ```bash docker compose up -d ``` ## Launcher einstellen In den Launcher-Einstellungen unter **Netzwerk → CurseForge** die Adresse eintragen, zum Beispiel `https://cf.example.de`. Das Feld „Eigener API-Key" bleibt leer – wer dort einen Schlüssel einträgt, geht direkt zu CurseForge und nutzt diesen Dienst nicht. Soll die Adresse für alle Nutzer voreingestellt sein, trage sie in `src/services.js` bei `STANDARD_WEITERLEITUNG` ein. Die Adresse ist kein Geheimnis, nur der Schlüssel ist eines. ## Absicherung Der Dienst steht offen im Netz. Eingebaut ist: - **Host-Liste** – durchgereicht wird nur an `edge.forgecdn.net`, `mediafilez.forgecdn.net` und `media.forgecdn.net`. Ohne diese Prüfung könnte jemand den Dienst Adressen in deinem Heimnetz abrufen lassen und die Antwort mitlesen. - **Umleitungen** werden selbst verfolgt und bei jedem Sprung erneut gegen die Host-Liste geprüft, höchstens vier Sprünge. - **Ratenbegrenzung** je Absender, einstellbar über `RATE_LIMIT_PER_MIN`. - **Größengrenze** für durchgereichte Dateien über `MAX_DOWNLOAD_MB`. - **Optionales Token** über `CF_PROXY_TOKEN`. Zum Token eine ehrliche Einordnung: Es steckt dann auch im Launcher und ist dort auslesbar. Es hält Gelegenheitsnutzer ab, keine entschlossenen. Die Ratenbegrenzung ist der wirksamere Schutz für dein Kontingent. ### Reverse-Proxy: `TRUST_PROXY` richtig setzen `TRUST_PROXY` ist keine Ja/Nein-Angabe, sondern die **Anzahl der Stufen** vor dem Dienst: `0` ohne Proxy, `1` mit Nginx Proxy Manager, `2` mit Cloudflare davor. Der Grund: nginx **ergänzt** `X-Forwarded-For`, statt es zu ersetzen. Schickt ein Aufrufer selbst `X-Forwarded-For: 1.2.3.4`, steht hinterher `1.2.3.4, ` darin. Deshalb wird von rechts gezählt – die eigenen Proxy-Stufen sind die einzigen Einträge, die niemand von außen setzen kann. Zu hoch angesetzt, greift der Dienst auf einen Eintrag zu, den der Aufrufer selbst erfunden hat: Dann kann sich jeder mit jeder Anfrage eine neue Adresse ausdenken und die Ratenbegrenzung ins Leere laufen lassen. Im Zweifel `0`. ### Nginx Proxy Manager Im Proxy Host eintragen: | Feld | Wert | |---|---| | Scheme | `http` | | Forward Hostname / IP | Containername oder LAN-Adresse des Dienstes | | Forward Port | `8420` | | Block Common Exploits | an | | Websockets Support | nicht nötig | Im Reiter **SSL**: Let's-Encrypt-Zertifikat anfordern, „Force SSL" und HTTP/2 aktivieren. Ohne HTTPS ginge das Token im Klartext über die Leitung. Im Reiter **Advanced** empfiehlt sich für die durchgereichten Mod-Dateien: ```nginx proxy_buffering off; proxy_read_timeout 300s; ``` Ohne `proxy_buffering off` schreibt nginx große Dateien erst vollständig in eine temporäre Datei, bevor der Launcher das erste Byte sieht – bei mehreren hundert MB fühlt sich das wie ein Hänger an. Läuft der Nginx Proxy Manager selbst in Docker, gehören beide ins gleiche Docker-Netz und der Port muss gar nicht nach außen gebunden werden: In der `docker-compose.yml` dann den `ports`-Block weglassen. Sonst wenigstens auf `127.0.0.1:8420:8420` einschränken, damit der Dienst nicht an der Absicherung des Proxys vorbei erreichbar ist. ## Was der Dienst nicht tut Er speichert nichts, protokolliert keine Adressen der Nutzer und gibt Schlüsselfehler von CurseForge nicht im Wortlaut nach außen weiter.