Running LightNVR on Windows with Podman + WSL2

August 17, 2026 · View on GitHub

Verified against LightNVR 0.37.x.

LightNVR is Linux software. There is no native Windows build and none is planned — on Windows you run the published Linux container. This guide uses Podman with the WSL2 backend, which is the lightest way to do that: no background desktop service, no daemon running as SYSTEM, and no subscription requirement for commercial use.

If you already run Docker Desktop and are happy with it, DOCKER.md applies unchanged — everything below is Podman-specific setup around the same image.

Time to first camera: about 20 minutes, most of it waiting on downloads.


Before you start

RequirementNotes
Windows 11Podman's WSL backend requires Windows 11 or later.
Hardware virtualization enabledCheck Task Manager → Performance → CPU → "Virtualization: Enabled". Enable in UEFI/BIOS if not.
~10 GB free on C:For WSL, the image, and headroom. Recordings need much more — see Storage.
Cameras reachable by IPRTSP/ONVIF over your LAN. USB webcams are not supported through WSL2.

A note on expectations: this runs a 24/7 recorder on a desktop OS. Windows sleeping, updating, or rebooting stops your recordings. Keeping it running covers what to change.


1. Install WSL2

Open PowerShell as Administrator:

wsl --install
wsl --update

Reboot if prompted, then confirm you are on WSL 2:

wsl --version

You do not need to install Ubuntu or any other distribution. Podman creates and manages its own.

2. Install Podman

In a normal (non-admin) PowerShell:

winget install RedHat.Podman

Close and reopen PowerShell so podman lands on your PATH, then:

podman --version

If you prefer a GUI — and you probably do for the autostart setting later — install Podman Desktop as well:

winget install RedHat.Podman-Desktop

3. Size the WSL VM

Podman's WSL backend shares one VM with all your WSL distributions, so its CPU and memory come from WSL's global config, not from podman machine set. By default WSL will take up to 50% of your RAM, which is more than LightNVR needs and more than you probably want a background recorder holding.

Create %UserProfile%\.wslconfig:

[wsl2]
memory=4GB
processors=4

4 GB is comfortable for a handful of cameras with detection enabled. Raise it if you run many streams or see the container getting OOM-killed.

Apply it:

wsl --shutdown

4. Create the Podman machine

podman machine init
podman machine start
podman info

podman machine init creates a WSL distribution named podman-machine-default. The machine runs rootless by default, which is what you want — LightNVR's ports are all above 1023, so nothing here needs root.


Storage: decide this before you start

This is the one decision that is painful to undo, so make it deliberately.

Do not put LightNVR's database or recordings on a C:\ path. Windows drives are exposed inside WSL through DrvFs (/mnt/c), which is slow for the small synchronous writes SQLite makes and does not implement POSIX file locking the way SQLite expects. That combination is how you get a corrupted database, and continuous video writes through DrvFs will underperform badly on top of it.

Use named volumes instead. They live on the ext4 filesystem inside the WSL virtual disk and behave exactly like they would on a Linux host:

podman volume create lightnvr-config
podman volume create lightnvr-data

Where does that actually live? Inside the WSL virtual disk on C:, which grows on demand up to 1 TB by default. You can browse it from Explorer at:

\\wsl.localhost\podman-machine-default\home\user\.local\share\containers\storage\volumes\

If you want recordings on a different, bigger drive, do not bind-mount D:\ into the container — move the whole WSL distribution to that drive instead, so everything stays on ext4:

podman machine stop
wsl --manage podman-machine-default --move D:\wsl\podman
podman machine start

5. Choose how you will reach the web UI

Podman on Windows publishes container ports against localhost (127.0.0.1) only. So http://localhost:8080 works on the Windows machine itself and nothing else on your network can reach it. For an NVR you almost certainly want to view it from a phone or another PC. Pick one of these two.

WSL's mirrored mode makes the VM share the host's network interfaces. This gets you LAN access and working multicast, which matters because ONVIF camera discovery uses multicast. It requires Windows 11 22H2 or higher.

Add to %UserProfile%\.wslconfig:

[wsl2]
memory=4GB
processors=4
networkingMode=mirrored

Then allow inbound connections through the Hyper-V firewall, in PowerShell as Administrator:

Set-NetFirewallHyperVVMSetting -Name '{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}' -DefaultInboundAction Allow

Restart WSL for both to take effect:

wsl --shutdown
podman machine start

Option B — NAT with port forwarding

If you are on Windows 10 or mirrored mode causes trouble (it can interact badly with some VPN clients), stay on the default NAT mode and forward the web port from the host:

netsh interface portproxy add v4tov4 listenport=8080 listenaddress=0.0.0.0 connectport=8080 connectaddress=127.0.0.1
New-NetFirewallRule -DisplayName "LightNVR Web UI" -Direction Inbound -Protocol TCP -LocalPort 8080 -Action Allow

Repeat for any other port you need to expose (8554 RTSP, 8555 WebRTC, 1984 go2rtc). With NAT, ONVIF auto-discovery by multicast will not work — see Adding cameras.


6. Run LightNVR

Replace 192.168.1.0/24 with your actual camera network and set your timezone:

podman run -d `
  --name lightnvr `
  --restart always `
  -p 8080:8080 `
  -p 8554:8554 `
  -p 8555:8555 `
  -p 8555:8555/udp `
  -p 1984:1984 `
  -v lightnvr-config:/etc/lightnvr `
  -v lightnvr-data:/var/lib/lightnvr/data `
  -e TZ=America/New_York `
  -e LIGHTNVR_ONVIF_NETWORK=192.168.1.0/24 `
  ghcr.io/opensensor/lightnvr:latest

(Those are PowerShell backticks for line continuation, not quotes. In CMD, use ^, or just put it all on one line.)

Watch it come up:

podman logs -f lightnvr

Then open http://localhost:8080.

Change the password immediately. The container ships with admin / admin and the web server binds to 0.0.0.0. Once you expose port 8080 to your LAN, those credentials are all that stands in front of your cameras. Change it under Settings → Users on first login.

Ports, and which ones you actually need

PortPurposeNeeded?
8080Web UI and APIAlways
1984go2rtc APIYes — the UI's live view uses it
8554RTSP restreamOnly if other apps pull streams from LightNVR
8555 TCP+UDPWebRTCOnly for low-latency live view from other devices

7. Adding cameras

LIGHTNVR_ONVIF_NETWORK is what makes discovery work from inside a container. LightNVR sweeps that CIDR range with unicast probes, which crosses NAT fine — this is why it is set in the run command above. It falls back to multicast WS-Discovery, and that part only works in mirrored networking mode.

So:

  • Mirrored mode — discovery works both ways. Use Settings → ONVIF Discovery.
  • NAT mode — set LIGHTNVR_ONVIF_NETWORK to the right subnet and discovery still works via the unicast sweep. If a camera does not appear, add it manually by RTSP URL.

Outbound connections to cameras work in either mode. NAT only breaks discovery, never recording.


Keeping it running

Four separate things can stop your recorder. Handle all four.

1. The container. --restart always is already in the run command. Make sure the service that acts on it is enabled inside the machine:

podman machine ssh 'systemctl --user enable --now podman-restart.service'
podman machine ssh 'sudo loginctl enable-linger $USER'

2. The Podman machine. It does not start itself when you log in. The simplest fix is Podman Desktop → Settings → Preferences, and enable the login/engine autostart options. Without a GUI, create a logon task:

$action  = New-ScheduledTaskAction -Execute "podman" -Argument "machine start"
$trigger = New-ScheduledTaskTrigger -AtLogOn
Register-ScheduledTask -TaskName "Start Podman Machine" -Action $action -Trigger $trigger

Note the consequence of rootless: the machine starts at logon, not at boot. If the PC reboots and nobody logs in, nothing records. If that is unacceptable, this workload wants a Linux host or a NAS, not a Windows desktop.

3. Windows sleeping. A sleeping PC records nothing.

powercfg /change standby-timeout-ac 0
powercfg /change hibernate-timeout-ac 0
powercfg /change disk-timeout-ac 0

4. Windows Update reboots. Set active hours, or accept the gaps.


Running it as a service instead (Quadlet)

If you would rather manage LightNVR as a systemd unit inside the machine than as a podman run invocation you have to remember, Podman's Quadlet does that. Remove the container from step 6 first, or the two will fight over the same ports:

podman rm -f lightnvr

Open a shell in the machine:

podman machine ssh

and from that Linux shell, write the unit:

mkdir -p ~/.config/containers/systemd
cat > ~/.config/containers/systemd/lightnvr.container <<'EOF'
[Unit]
Description=LightNVR

[Container]
Image=ghcr.io/opensensor/lightnvr:latest
AutoUpdate=registry
PublishPort=8080:8080
PublishPort=8554:8554
PublishPort=8555:8555
PublishPort=8555:8555/udp
PublishPort=1984:1984
Volume=lightnvr-config:/etc/lightnvr
Volume=lightnvr-data:/var/lib/lightnvr/data
Environment=TZ=America/New_York
Environment=LIGHTNVR_ONVIF_NETWORK=192.168.1.0/24

[Service]
Restart=always

[Install]
WantedBy=default.target
EOF

systemctl --user daemon-reload
systemctl --user start lightnvr
exit

AutoUpdate=registry lets podman auto-update pull new releases in place.


Updating

podman pull ghcr.io/opensensor/lightnvr:latest
podman stop lightnvr
podman rm lightnvr
# re-run the podman run command from step 6

Your config and recordings are in the named volumes, so they survive. Pin a version tag instead of latest (for example ghcr.io/opensensor/lightnvr:0.37.1) if you would rather choose when to move.

Backing up

The database and recordings both live in lightnvr-data. To pull a copy out to Windows:

podman cp lightnvr:/var/lib/lightnvr/data/database C:\lightnvr-backup\

Or browse the volume directly in Explorer through \\wsl.localhost\podman-machine-default\. Copying out through DrvFs is fine — it is only running the live database on it that causes problems.


Troubleshooting

SymptomCauseFix
podman machine start fails with a WSL errorWSL not updatedwsl --update, then retry
Web UI works on the PC but not from a phonePorts bind to 127.0.0.1 onlyMirrored mode, or netsh portproxystep 5
ONVIF discovery finds nothingMulticast does not cross NATSet LIGHTNVR_ONVIF_NETWORK to your camera subnet, or switch to mirrored mode
Recording timestamps are wrongTimezone not setPass -e TZ=Your/Zone
"database is locked", corruptionDatabase on a C:\ bind mountMove to a named volume — Storage
Container killed unexpectedlyWSL VM memory too lowRaise memory= in .wslconfig, wsl --shutdown, restart
Everything stops after a rebootMachine only starts at logonKeeping it running
Live view black, UI otherwise finego2rtc port not publishedEnsure -p 1984:1984

Container logs are the first place to look:

podman logs --tail 100 lightnvr

For problems that are not Windows-specific, TROUBLESHOOTING.md and TROUBLESHOOTING_WEB_INTERFACE.md apply here too.


Uninstalling

podman stop lightnvr
podman rm lightnvr
podman volume rm lightnvr-config lightnvr-data   # deletes recordings
podman machine stop
podman machine rm podman-machine-default
winget uninstall RedHat.Podman

If you added port proxies, remove them:

netsh interface portproxy delete v4tov4 listenport=8080 listenaddress=0.0.0.0

See also