# CS2 Mapveto als Container betreiben CS2 Mapveto läuft als **ein** Container: Webseite, Backend, Datenbank (SQLite) und ein Docker-Client. Er steht auf demselben Docker-Host wie die CS2-Server und startet pro Match über `/var/run/docker.sock` einen eigenen CS2-Container (Docker-Adapter). Ein PC mit Node.js oder SSH wird dafür nicht mehr gebraucht. ``` Docker-Host (z. B. amp-cluster, 192.168.178.111) ├── cs2-mapveto ← dieser Container, Port 3000 ├── cs2mv- ← CS2-Server pro Match, Ports ab 27100 (startet/entfernt CS2 Mapveto) ├── Volume cs2-mapveto-gamefiles CS2-Spieldateien (~73 GB, einmal befüllt) └── Volume cs2-mapveto-data Datenbank von CS2 Mapveto ``` > **Nur eine Instanz pro Docker-Host.** Läuft CS2 Mapveto zusätzlich auf einem PC mit `SERVER_ADAPTER=docker` > und demselben Docker-Host, vergeben beide unabhängig voneinander Ports und Containernamen. Die PC-Instanz > also beenden oder auf einen anderen Adapter stellen, bevor der Container läuft. --- ## 1. Image bauen Das Image wird auf dem Docker-Host gebaut, beim Bauen laufen auch alle Tests. Am einfachsten vom PC aus, im Projektordner, über den SSH-Zugang zum Host: ```powershell docker -H ssh://cs2docker build -t cs2-mapveto:latest . ``` Ergebnis: Image `cs2-mapveto:latest` (~300 MB) auf dem Host. Alternativ direkt auf dem Host nach einem `git clone` des Repositorys: `docker build -t cs2-mapveto:latest .` > Meldet Docker unter Windows `docker-credential-desktop: executable file not found`, kommt das von einer > Docker-Desktop-Einstellung. Abhilfe für den einen Befehl: `$env:DOCKER_CONFIG = "$env:TEMP\dockercfg"` > (Ordner mit einer Datei `config.json`, Inhalt `{}`). ## 2. Stack in Portainer anlegen Portainer → **Stacks** → **+ Add stack** → Name `cs2-mapveto` → *Web editor*: ```yaml services: cs2-mapveto: image: cs2-mapveto:latest container_name: cs2-mapveto restart: unless-stopped ports: - "3000:3000" environment: - PUBLIC_URL=http://192.168.178.111:3000 - LOG_RECEIVER_URL=http://192.168.178.111:3000 - SERVER_ADAPTER=docker - CS2_PUBLIC_HOST=192.168.178.111 - CS2_RCON_HOST=192.168.178.111 - CS2_GSLT= - CS2_DOCKER_VOLUME=cs2-mapveto-gamefiles - CS2_DOCKER_IMAGE=joedwards32/cs2:latest - CS2_PORT_RANGE_START=27100 - CS2_PORT_RANGE_END=27139 - CREATE_MATCH_PASSWORD= - STREAM_KEY= - SERIES_AUTO_ADVANCE_SECONDS=30 - SERVER_IDLE_TIMEOUT_MINUTES=30 volumes: - cs2-mapveto-data:/data - /var/run/docker.sock:/var/run/docker.sock volumes: cs2-mapveto-data: name: cs2-mapveto-data ``` **Deploy the stack.** Danach ist CS2 Mapveto unter `http://192.168.178.111:3000` erreichbar, die Stream-Übersicht unter `/stream`. Dieselbe Datei liegt als [`compose.yml`](../compose.yml) im Repository (dort zusätzlich mit `build: .`, für `docker compose up -d --build` direkt auf dem Host). ### Einstellungen Alle Umgebungsvariablen aus [`.env.example`](../.env.example) funktionieren auch hier. Die wichtigsten: | Variable | Bedeutung | |---|---| | `PUBLIC_URL` | Adresse der Webseite für Einladungslinks | | `LOG_RECEIVER_URL` | Adresse, an die die CS2-Container ihre Logs schicken (Live-Ergebnisse) | | `CS2_PUBLIC_HOST` / `CS2_RCON_HOST` | IP des Docker-Hosts – Spieler verbinden sich dorthin, CS2 Mapveto steuert die Server darüber | | `CS2_GSLT` | leer = LAN-Modus; mit Token öffentlich erreichbar (ein Token pro gleichzeitigem Match) | | `CS2_PORT_RANGE_START/END` | Ports für Match-Container, zwei pro Match, in der Firewall freigeben | | `CREATE_MATCH_PASSWORD` | Passwort zum Anlegen von Matches | | `STREAM_KEY` | Schlüssel für `/stream?key=…` | **Passwörter und Schlüssel nur aus Buchstaben und Ziffern** wählen. ## 3. Updaten 1. Neues Image bauen (Schritt 1, gleicher Befehl). 2. Portainer → Stack `cs2-mapveto` → **Update the stack** (bzw. Container → *Recreate*). Die Datenbank liegt im Volume `cs2-mapveto-data` und bleibt erhalten. Laufende Match-Container übernimmt CS2 Mapveto nach dem Neustart wieder; ein Serverstart, der gerade lief, wird als unterbrochen markiert und lässt sich mit „Server neu starten“ wiederholen. ## 4. Sicherheit Der Container hat über `/var/run/docker.sock` volle Kontrolle über Docker auf dem Host – das ist nötig, um Match-Container zu starten, entspricht aber Root-Rechten auf dem Host. Deshalb: - Port 3000 nur im LAN anbieten, nicht ins Internet weiterleiten. - `CREATE_MATCH_PASSWORD` setzen, wenn nicht jeder im LAN Matches anlegen soll. - RCON-Ports (TCP 27100–27139) möglichst nur vom Host bzw. LAN erreichbar lassen. ## 5. Fehlersuche | Symptom | Ursache / Lösung | |---|---| | „Server wird angefordert“ bleibt stehen | Container-Log prüfen (Portainer → `cs2-mapveto` → Logs); Docker-Socket eingebunden? | | `permission denied … docker.sock` im Log | Socket nicht eingebunden oder Docker mit Rootless-Modus – Pfad zum Socket anpassen | | Match-Container startet, „Server startet“ endet in Fehler | Ports 27100+ von `CS2_RCON_HOST` aus erreichbar? Firewall des Hosts | | Keine Live-Ergebnisse | `LOG_RECEIVER_URL` muss die Host-IP mit Port 3000 sein, nicht `localhost` | | Port bereits belegt | Eine zweite CS2-Mapveto-Instanz nutzt denselben Host (siehe Hinweis oben) |