---
url: /de/remote/reverse-proxy.md
---

# Reverse-Proxy

Hinter Apache, nginx, Traefik oder einem anderen Reverse-Proxy braucht camera.ui mehr als reines HTTP: Live-Video, Events und die Kameraliste laufen über WebSockets. Ein Proxy, der nur normale Anfragen weiterleitet, liefert eine Oberfläche, die lädt und leer bleibt.

## Was der Server erwartet

**Der Hauptport liefert HTTPS aus.** camera.ui lauscht standardmäßig auf Port `3443`, mit einem selbst erzeugten Zertifikat. Ein Proxy, der auf diesen Port zeigt, muss sich mit `https://` verbinden und die Zertifikatsprüfung abschalten, da es keinen öffentlichen Aussteller zum Prüfen gibt. Alternativ schaltest du einen [reinen HTTP-Port](#stattdessen-reines-http) ein.

**WebSocket-Upgrades müssen den Server erreichen.** Sie laufen über denselben Host und Port wie der Rest der App. Am einfachsten leitest du alles unter `/` samt Upgrades weiter.

**Verbindungen bleiben lange offen.** Ein Live-Stream hält eine Verbindung so lange, wie du zusiehst. Proxy-Timeouts im Sekundenbereich zerschneiden das Bild in regelmäßigen Abständen.

**Nur ein vertrauenswürdiger Proxy reicht die Adresse des Clients weiter.** camera.ui liest `X-Forwarded-For` von einem Proxy auf derselben Maschine, der sich über `127.0.0.1` oder `::1` verbindet, und von den Adressen, denen du [vertraust](#proxy-auf-einer-anderen-maschine). Hinter jedem anderen Proxy zeigen die Sitzungslisten die Adresse des Proxys.

## Apache

Aktiviere `proxy`, `proxy_http`, `proxy_wstunnel`, `ssl` und `headers` und nutze dann diesen Virtual Host:

```apache
<VirtualHost *:443>
  ServerName nvr.example.com

  ProxyPreserveHost On
  ProxyRequests Off

  SSLProxyEngine On
  SSLProxyVerify none
  SSLProxyCheckPeerCN off
  SSLProxyCheckPeerName off
  SSLProxyCheckPeerExpire off

  ProxyTimeout 300

  ProxyPass        "/" "https://10.0.0.27:3443/" upgrade=websocket timeout=300
  ProxyPassReverse "/" "https://10.0.0.27:3443/"

  RequestHeader set X-Forwarded-Proto "https"
  RequestHeader set X-Forwarded-Port "443"
</VirtualHost>
```

Die Option `upgrade=websocket` braucht Apache 2.4.47 oder neuer (`apachectl -v`). Auf älteren Versionen lässt du die Option weg und leitest die Upgrades stattdessen über `mod_rewrite`:

```apache
  ProxyPass        "/" "https://10.0.0.27:3443/"
  ProxyPassReverse "/" "https://10.0.0.27:3443/"

  RewriteEngine On
  RewriteCond %{HTTP:Upgrade} =websocket [NC]
  RewriteCond %{HTTP:Connection} upgrade [NC]
  RewriteRule /(.*) wss://10.0.0.27:3443/$1 [P,L]
```

Das Rewrite-Ziel muss `wss://` sein. Mit `ws://` geht der Handshake unverschlüsselt an einen TLS-Port, Apache protokolliert `error reading status line from remote server`, und jeder WebSocket scheitert mit einem 502, während normale Seiten problemlos laden.

## nginx

```nginx
map $http_upgrade $connection_upgrade {
  default upgrade;
  ''      close;
}

server {
  listen 443 ssl;
  server_name nvr.example.com;

  client_max_body_size 100m;

  location / {
    proxy_pass https://10.0.0.27:3443;
    proxy_ssl_verify off;

    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;

    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    proxy_buffering off;
    proxy_read_timeout 300s;
  }
}
```

`client_max_body_size` ist wichtig, wenn du ein Backup über den Proxy einspielst, denn nginx lehnt Uploads über 1 MB standardmäßig ab.

## Proxy auf einer anderen Maschine

Damit die Sitzungslisten hinter einem Proxy auf einem anderen Host die Adresse des Clients zeigen, trag den Proxy unter **Vertrauenswürdige Proxys** in der Karte **Reverse-Proxy** unter **Einstellungen → Remote Zugriff** ein. Ein Eintrag ist eine IP-Adresse oder ein Bereich wie `10.0.0.0/24`, er gilt beim Speichern. Eine eingetragene Adresse kann jede beliebige Client-Adresse weiterreichen, trag also nur den Proxy ein.

In Docker setzt `CAMERA_UI_TRUSTED_PROXIES=10.0.0.5` die Liste stattdessen, mehrere Einträge durch Kommas getrennt. Das Feld nennt dann die Variable und bleibt gesperrt, und einen Eintrag, den camera.ui nicht lesen kann, überspringt es und nennt ihn im Log.

## Stattdessen reines HTTP

camera.ui kann einen zweiten Listener öffnen, der reines HTTP spricht und alles inklusive WebSockets an den Hauptport weiterreicht. Trag einen Port, etwa `8081`, als **HTTP-Port** unter **Einstellungen → [System](/de/admin/system#server)** ein und speichere, oder setze in Docker `CAMERA_UI_INSECURE_PORT=8081`. Richte den Proxy dann auf `http://10.0.0.27:8081` und lass die `SSLProxy*`-Zeilen beziehungsweise `proxy_ssl_verify` weg.

Dieser Listener bindet sich an dieselbe Adresse wie der Hauptport, ist also in deinem gesamten Netzwerk unverschlüsselt erreichbar. Nutze ihn nur dort, wo dieser Verkehr vertrauenswürdig bleibt, etwa bei einem Proxy auf derselben Maschine oder in einem Netzsegment, das du kontrollierst.

## Andere Websites

Eine Seite unter einer anderen Adresse, etwa ein Dashboard, kann die API von camera.ui aus dem Browser nur aufrufen, wenn ihre Adresse unter **Erlaubte Websites** in der Karte **Reverse-Proxy** steht, als `https://dashboard.example.com`.

## Wenn die Oberfläche lädt, aber leer bleibt

Kameras zeigen einen Platzhalter, die Event-Zeile füllt sich nie, nichts aktualisiert sich. Das ist ein WebSocket-Problem, kein Anmeldeproblem. Filtere in den Entwicklertools des Browsers den Netzwerk-Tab nach WS und lade neu. Ein fehlgeschlagener Eintrag mit Status 502 oder 400 bestätigt es, das Fehlerprotokoll deines Proxys nennt den Grund.

## Hinter einem Login-Proxy

Mit Pangolin, Authelia oder einem anderen Proxy mit eigener Anmeldung laufen Seitenaufrufe immer über den Proxy, damit er erneut fragen kann, wenn seine Sitzung abläuft. Bleibt ein Browser trotzdem bei **Server nicht erreichbar** stehen, lösche dort einmal die Websitedaten von camera.ui und öffne die Seite neu. Wie du hinter so einem Proxy die Anmeldung von camera.ui überspringst, steht unter [Anmeldung über Proxy](/de/remote/proxy-sign-in).

## camera.ui die Adresse mitteilen

Sobald der Proxy läuft, trägst du die öffentliche Adresse unter **Einstellungen → Remote Zugriff** ein, wie unter [Eigene Domain](/de/remote/custom-domain) beschrieben.

Antwortet der Proxy auch in deinem eigenen Netzwerk, trag seine Adresse unter **Lokale Adresse** in der Karte **Netzwerk** auf derselben Seite ein, etwa `https://camera.home.lan`. Apps sprechen zuhause dann mit dem Proxy statt mit der IP des Servers. Apps, die über [camera.ui Cloud](/de/remote/cloud) verbinden, tun das nur bei einem lokalen Namen, etwa mit `.lan`, `.local` oder `.home.arpa` am Ende, oder bei einem Namen ohne Punkt. Jeden anderen Namen behandeln sie als Internetadresse. Der Proxy braucht ein Zertifikat für diesen Namen und muss WebSocket-Verbindungen durchreichen, genau wie für den Zugriff von außen. Außerdem muss er `OPTIONS`-Anfragen an camera.ui weiterreichen und dessen `Access-Control-*`-Header unverändert durchlassen, weil die Apps ihn von einem anderen Origin aus aufrufen. Sonst nehmen sie zuhause den Weg übers Internet. Kamera-Streams nutzen weiterhin die IP-Adressen unter **Server-Adressen** darüber, lass die also unangetastet.

**Verbindung testen** prüft die Adresse, indem der Server sie selbst aufruft. Beherrscht dein Router kein Hairpin-NAT oder schickt internes DNS den Namen woandershin, kommt diese Anfrage nie zurück und der Test schlägt fehl, obwohl die Adresse von außen funktioniert. Der Remote-Zugriff läuft trotzdem weiter: camera.ui gibt eine eigene Domain erst auf, wenn der Name im öffentlichen Internet nicht mehr auflöst. Ein interner DNS-Eintrag, der auf den Proxy zeigt, lässt auch den Test durchlaufen.

## Nächste Schritte

**[Eigene Domain](/de/remote/custom-domain)** — die öffentliche Adresse in camera.ui eintragen.
**[camera.ui Cloud](/de/remote/cloud)** — Fernzugriff, ohne am Netzwerk etwas zu ändern.
