fix: go2rtc proxied through NextNVR — no port 1984 forwarding needed

This commit is contained in:
Claus Lohmar 2026-08-05 14:42:09 +01:00
parent 66dd4c54b4
commit faf954a59d
3 changed files with 17 additions and 8 deletions

View file

@ -52,16 +52,11 @@ Once done, open the web interface in your browser (the script prints the URL).
To access NextNVR from outside your home network: To access NextNVR from outside your home network:
1. **Dynamic DNS** — use a free provider like DuckDNS, No-IP, or Cloudflare to get a domain name (e.g. `myhouse.duckdns.org`) 1. **Dynamic DNS** — use a free provider like DuckDNS, No-IP, or Cloudflare to get a domain name (e.g. `myhouse.duckdns.org`)
2. **Port forwarding** — in your router settings, forward these ports to the NextNVR server: 2. **Port forwarding** — in your router settings, forward port `8080` to the NextNVR server
| Port | Service | Required |
|------|---------|----------|
| `8080` | Web UI | Yes |
| `1984` | Live streaming | **Yes — live view won't work without it** |
Then access your cameras from anywhere: `http://myhouse.duckdns.org:8080` Then access your cameras from anywhere: `http://myhouse.duckdns.org:8080`
> ⚠️ For production use, put NextNVR behind a reverse proxy (like Zoraxy or Nginx) with HTTPS to secure your connection. > ⚠️ For production use, put NextNVR behind a reverse proxy (like Zoraxy or Nginx) with HTTPS. Only port 443 needs to be forwarded — live streams are proxied through NextNVR automatically.
--- ---

View file

@ -96,7 +96,7 @@ function renderLiveGrid() {
function openFocus(cam) { function openFocus(cam) {
const overlay = document.getElementById('focus-overlay'); const overlay = document.getElementById('focus-overlay');
overlay.classList.remove('hidden'); overlay.classList.remove('hidden');
document.getElementById('focus-frame').src = `http://${location.hostname}:1984/stream.html?src=${cam.id}_sub`; document.getElementById('focus-frame').src = `/go2rtc/stream.html?src=${cam.id}_sub`;
} }
document.getElementById('focus-close').addEventListener('click', () => { document.getElementById('focus-close').addEventListener('click', () => {
document.getElementById('focus-overlay').classList.add('hidden'); document.getElementById('focus-overlay').classList.add('hidden');

View file

@ -8,6 +8,8 @@ import (
"io/fs" "io/fs"
"log" "log"
"net/http" "net/http"
"net/http/httputil"
"net/url"
"strings" "strings"
) )
@ -53,6 +55,13 @@ func (s *Server) Close() {
} }
} }
// go2rtcProxy returns a reverse proxy to go2rtc on port 1984.
// Used to avoid mixed-content blocking when NextNVR is behind HTTPS.
func (s *Server) go2rtcProxy() http.Handler {
target, _ := url.Parse("http://127.0.0.1:1984")
return httputil.NewSingleHostReverseProxy(target)
}
// registerRoutes sets up all API and static file routes. // registerRoutes sets up all API and static file routes.
func (s *Server) registerRoutes() { func (s *Server) registerRoutes() {
// API endpoints. // API endpoints.
@ -66,6 +75,11 @@ func (s *Server) registerRoutes() {
// Live MJPEG stream proxy — proxied through NextNVR to avoid cross-origin issues. // Live MJPEG stream proxy — proxied through NextNVR to avoid cross-origin issues.
s.mux.HandleFunc("/stream/", s.handleStream) s.mux.HandleFunc("/stream/", s.handleStream)
// go2rtc reverse proxy — serves the go2rtc web UI and API through NextNVR.
// This avoids mixed-content blocking when NextNVR is behind HTTPS.
s.mux.Handle("/go2rtc/", http.StripPrefix("/go2rtc",
s.go2rtcProxy()))
// Static file server for recordings (actual video files on disk). // Static file server for recordings (actual video files on disk).
s.mux.Handle("/recordings/", http.StripPrefix("/recordings/", s.mux.Handle("/recordings/", http.StripPrefix("/recordings/",
http.FileServer(http.Dir(s.config.Storage.RecordingsPath)))) http.FileServer(http.Dir(s.config.Storage.RecordingsPath))))