5 Deployment
Forgeagent edited this page 2026-07-20 10:25:28 +02:00

Installation, TLS und Beispiel-Deployments

Build und Installation

Voraussetzung ist die in go.mod angegebene Go-Version. Ein statisches Binary wird reproduzierbar gebaut:

git clone https://repository.hildebrandt.io/ai-tools/private-proxy-mcp.git
cd private-proxy-mcp
make reproducible-build
install -m 0755 build/private-proxy-mcp /usr/local/bin/private-proxy-mcp

Offizielle Tag-Builds enthalten Archive für Linux amd64/arm64, macOS arm64 und Windows amd64. Nach dem Download wird zuerst die Prüfsumme geprüft:

sha256sum -c checksums.txt
tar -xzf private-proxy-mcp_v1.2.3_linux_amd64.tar.gz

Bereits installierte Binaries aktualisieren sich mit private-proxy-mcp update gegen die Forgejo-Releases (siehe CLI.md).

Konfigurationen werden getrennt auf öffentlichem und privatem Host abgelegt, beispielsweise unter /etc/private-proxy-mcp/server.yaml und /etc/private-proxy-mcp/proxy.yaml. Dateien mit Shared Key erhalten Modus 0600 und einen eigenen, unprivilegierten Service-Account.

Empfohlenes Deployment mit TLS-Reverse-Proxy

Öffentlicher Host:

mcp:
  listen_address: 127.0.0.1:9334
private_proxy:
  listen_address: 127.0.0.1:9335
  shared_key: "REPLACE_FROM_SECRET_STORE"

Der vorgeschaltete Reverse-Proxy terminiert TLS auf zwei externen Routen:

  • https://mcp.example:443/mcphttp://127.0.0.1:9334/mcp; hier findet die MCP-Client-Authentisierung statt.
  • https://connector.example:9335/connectorhttp://127.0.0.1:9335/connector; HTTP/1.1 Upgrade und lange Lese-/Schreibzeiten müssen erhalten bleiben. HTTP/2 wird für diese Route deaktiviert.

Privater Host:

private_proxy:
  connector_url: https://connector.example:9335/connector
  shared_key: "REPLACE_FROM_SECRET_STORE"
http:
  network_policy:
    allowed_hosts: [service.example]
    allowed_ports: [443]

Start:

private-proxy-mcp --config /etc/private-proxy-mcp/server.yaml mcp-server
private-proxy-mcp --config /etc/private-proxy-mcp/proxy.yaml private-proxy

Firewall-Regeln erlauben extern nur TLS-Endpunkte. Port 9334 und der interne Backend-Port 9335 bleiben loopback-gebunden; der private Host benötigt nur ausgehenden Zugriff zum Connector und zu ausdrücklich erlaubten Zielen.

Direktes MCP-Exposure hinter einem Proxy

Wenn der MCP-Prozess wegen Container-/Pod-Netzwerk auf Non-Loopback lauschen muss, sind beide Schutzschalter zwingend:

mcp:
  listen_address: 0.0.0.0:9334
  tls_terminated_by_proxy: true
  allowed_origins: [https://client.example]
  trusted_proxy_cidrs: [192.0.2.0/24]

Die Beispiel-CIDR ist ausschließlich ein reserviertes Dokumentationsnetz. In Produktion wird sie durch das engste tatsächliche Proxy-Netz ersetzt. Der Reverse-Proxy entfernt eingehende Forwarded-Header, setzt sie neu und erzwingt Authentisierung vor Weiterleitung. tls_terminated_by_proxy aktiviert selbst weder TLS noch Authentisierung.

TLS-Vertrauen des privaten Proxy

Öffentlich vertrauenswürdige Zertifikate benötigen keine Zusatzoption. Für eine private CA:

private_proxy:
  connector_url: https://connector.example:9335/connector
  tls_ca_file: /etc/private-proxy-mcp/connector-ca.pem
  tls_server_name: connector.example

Mindestens TLS 1.2 wird verwendet. Zertifikatskette, Gültigkeit und Servername werden geprüft. insecure_skip_verify und Klartext-HTTP sind keine Produktionsoptionen.

Container- und Service-Härtung

Pro Tag werden zwei Images als Multi-Arch-Manifeste für linux/amd64 und linux/arm64 veröffentlicht:

docker pull repository.hildebrandt.io/ai-tools/private-proxy-mcp/mcp:v1.2.3
docker pull repository.hildebrandt.io/ai-tools/private-proxy-mcp/proxy:v1.2.3

Das MCP-Image startet mcp-server, das Proxy-Image private-proxy. Beide laufen als nonroot. Da der MCP-Listener im Container von außen erreichbar sein muss, setzt die Server-Konfiguration mcp.listen_address explizit auf 0.0.0.0:9334 und aktiviert die Schutzschalter für den vorgeschalteten TLS-/Authentisierungs-Proxy:

mcp:
  listen_address: 0.0.0.0:9334
  tls_terminated_by_proxy: true
  allowed_origins: [https://client.example]
  trusted_proxy_cidrs: [172.20.0.0/16]
private_proxy:
  listen_address: 0.0.0.0:9335
  shared_key: "REPLACE_FROM_SECRET_STORE"

Beispielstart mit read-only Root-Dateisystem:

docker run --rm --read-only --cap-drop=ALL \
  -p 127.0.0.1:9334:9334 -p 127.0.0.1:9335:9335 \
  -v "$PWD/server.yaml:/config/server.yaml:ro" \
  repository.hildebrandt.io/ai-tools/private-proxy-mcp/mcp:v1.2.3 \
  --config /config/server.yaml mcp-server

docker run --rm --read-only --cap-drop=ALL \
  -v "$PWD/proxy.yaml:/config/proxy.yaml:ro" \
  repository.hildebrandt.io/ai-tools/private-proxy-mcp/proxy:v1.2.3 \
  --config /config/proxy.yaml private-proxy
  • read-only Root-Dateisystem, eigener UID/GID und keine zusätzlichen Capabilities;
  • nur die erforderlichen CA-, Config- und Secret-Dateien einhängen;
  • für Media/Browser separate beschreibbare Temp-Verzeichnisse mit Quota;
  • Browser-Prozessbaum zusätzlich über cgroups begrenzen;
  • ausgehende Firewallregeln als zweite Schranke neben der Anwendungs-Policy;
  • Liveness über /health/live, Readiness über /health/ready prüfen;
  • bei Shutdown mindestens mcp.shutdown_timeout beziehungsweise private_proxy.drain_timeout als Grace Period gewähren.

Browser auf macOS und Windows

Chromium und optional der Playwright-Sidecar laufen nur auf dem private-proxy-Host. Setup-Schritte, Pfadbeispiele und Troubleshooting:

Kurzfassung:

  1. Chrome for Testing pinnen (kein Auto-Download zur Laufzeit).
  2. executable_path + executable_version setzen und mit --version prüfen.
  3. Default-Backend chromedp; für Playwright Node LTS + npm ci im Sidecar- Verzeichnis und die Playwright-Pfade konfigurieren.
  4. Unprivilegiertes Konto, beschreibbares temp_root.