This is a project to build and publish docker images for various Network Optix VMS products.
10K+
Docker images for Network Optix Nx Witness and OEM-branded VMS products.
This is a project to build and publish Docker images for various [Network Optix][networkoptix-link] VMS products, in an Ubuntu and a [LinuxServer][lsio-link] base image variant of each product.
[![Release Status][releasebuildstatus-shield]][actions-link]
[![Last Commit][lastcommit-shield]][github-link]
[![GitHub Release][github-release-shield]][releases-link]
[![GitHub Pre-Release][github-pre-release-shield]][releases-link]
Docker releases:
[NxWitness][nxwitness-docker-hub-link]:
[![NxWitness Stable][hubnxwitnessstable-shield]][nxwitness-docker-hub-link]
[![NxWitness Latest][hubnxwitnesslatest-shield]][nxwitness-docker-hub-link]
[![NxWitness RC][hubnxwitnessrc-shield]][nxwitness-docker-hub-link]
[![NxWitness Beta][hubnxwitnessbeta-shield]][nxwitness-docker-hub-link]
[NxWitness-LSIO][nxwitness-lsio-docker-hub-link]:
[![NxWitness-LSIO Stable][hubnxwitnesslsiostable-shield]][nxwitness-lsio-docker-hub-link]
[![NxWitness-LSIO Latest][hubnxwitnesslsiolatest-shield]][nxwitness-lsio-docker-hub-link]
[![NxWitness-LSIO RC][hubnxwitnesslsiorc-shield]][nxwitness-lsio-docker-hub-link]
[![NxWitness-LSIO Beta][hubnxwitnesslsiobeta-shield]][nxwitness-lsio-docker-hub-link]
[NxMeta][nxmeta-docker-hub-link]:
[![NxMeta Stable][hubnxmetastable-shield]][nxmeta-docker-hub-link]
[![NxMeta Latest][hubnxmetalatest-shield]][nxmeta-docker-hub-link]
[![NxMeta RC][hubnxmetarc-shield]][nxmeta-docker-hub-link]
[![NxMeta Beta][hubnxmetabeta-shield]][nxmeta-docker-hub-link]
[NxMeta-LSIO][nxmeta-lsio-docker-hub-link]:
[![NxMeta-LSIO Stable][hubnxmetalsiostable-shield]][nxmeta-lsio-docker-hub-link]
[![NxMeta-LSIO Latest][hubnxmetalsiolatest-shield]][nxmeta-lsio-docker-hub-link]
[![NxMeta-LSIO RC][hubnxmetalsiorc-shield]][nxmeta-lsio-docker-hub-link]
[![NxMeta-LSIO Beta][hubnxmetalsiobeta-shield]][nxmeta-lsio-docker-hub-link]
[NxGo][nxgo-docker-hub-link]:
[![NxGo Stable][hubnxgostable-shield]][nxgo-docker-hub-link]
[![NxGo Latest][hubnxgolatest-shield]][nxgo-docker-hub-link]
[![NxGo RC][hubnxgorc-shield]][nxgo-docker-hub-link]
[![NxGo Beta][hubnxgobeta-shield]][nxgo-docker-hub-link]
[NxGo-LSIO][nxgo-lsio-docker-hub-link]:
[![NxGo-LSIO Stable][hubnxgolsiostable-shield]][nxgo-lsio-docker-hub-link]
[![NxGo-LSIO Latest][hubnxgolsiolatest-shield]][nxgo-lsio-docker-hub-link]
[![NxGo-LSIO RC][hubnxgolsiorc-shield]][nxgo-lsio-docker-hub-link]
[![NxGo-LSIO Beta][hubnxgolsiobeta-shield]][nxgo-lsio-docker-hub-link]
[DWSpectrum][dwspectrum-docker-hub-link]:
[![DWSpectrum Stable][hubdwspectrumstable-shield]][dwspectrum-docker-hub-link]
[![DWSpectrum Latest][hubdwspectrumlatest-shield]][dwspectrum-docker-hub-link]
[![DWSpectrum RC][hubdwspectrumrc-shield]][dwspectrum-docker-hub-link]
[![DWSpectrum Beta][hubdwspectrumbeta-shield]][dwspectrum-docker-hub-link]
[DWSpectrum-LSIO][dwspectrum-lsio-docker-hub-link]:
[![DWSpectrum-LSIO Stable][hubdwspectrumlsiostable-shield]][dwspectrum-lsio-docker-hub-link]
[![DWSpectrum-LSIO Latest][hubdwspectrumlsiolatest-shield]][dwspectrum-lsio-docker-hub-link]
[![DWSpectrum-LSIO RC][hubdwspectrumlsiorc-shield]][dwspectrum-lsio-docker-hub-link]
[![DWSpectrum-LSIO Beta][hubdwspectrumlsiobeta-shield]][dwspectrum-lsio-docker-hub-link]
[WisenetWAVE][wisenetwave-docker-hub-link]:
[![WisenetWAVE Stable][hubwisenetwavestable-shield]][wisenetwave-docker-hub-link]
[![WisenetWAVE Latest][hubwisenetwavelatest-shield]][wisenetwave-docker-hub-link]
[![WisenetWAVE RC][hubwisenetwaverc-shield]][wisenetwave-docker-hub-link]
[![WisenetWAVE Beta][hubwisenetwavebeta-shield]][wisenetwave-docker-hub-link]
[WisenetWAVE-LSIO][wisenetwave-lsio-docker-hub-link]:
[![WisenetWAVE-LSIO Stable][hubwisenetwavelsiostable-shield]][wisenetwave-lsio-docker-hub-link]
[![WisenetWAVE-LSIO Latest][hubwisenetwavelsiolatest-shield]][wisenetwave-lsio-docker-hub-link]
[![WisenetWAVE-LSIO RC][hubwisenetwavelsiorc-shield]][wisenetwave-lsio-docker-hub-link]
[![WisenetWAVE-LSIO Beta][hubwisenetwavelsiobeta-shield]][wisenetwave-lsio-docker-hub-link]
Version: 2.15:
Summary:
See [Release History][history] for complete release notes and older versions.
Getting started with a simple test compose file:
# compose.yaml
# Test using non persistent docker volumes
volumes:
test_nxwitness-lsio_config:
test_nxwitness-lsio_media:
test_nxwitness-lsio_backup:
test_nxwitness-lsio_analytics:
services:
nxwitness-lsio:
# Use the image matching your product
image: docker.io/ptr727/nxwitness-lsio:stable
container_name: nxwitness-lsio-test-container
restart: unless-stopped
network_mode: bridge
ports:
# Expose the service on port 7203
- 7203:7001
environment:
- TZ=America/Los_Angeles
volumes:
# Map to your real storage in production
- test_nxwitness-lsio_config:/config
- test_nxwitness-lsio_media:/media
- test_nxwitness-lsio_backup:/backup
- test_nxwitness-lsio_analytics:/analytics
tmpfs:
# Keep mediaserver's Unix socket and tmp files in RAM
- /tmp:size=1g,mode=1777
# Launch the service
docker compose up --detach
# Open your web browser on the local machine port 7203
echo "Nx Witness LSIO:" "https://$HOSTNAME:7203/"
# Shut the service down
docker compose down
Example of a service in production:
networks:
public_network: # External macvlan network
name: ${PUBLIC_NETWORK_NAME}
external: true
local_network: # External bridge network
name: ${LOCAL_NETWORK_NAME}
external: true
stack_network: # Stack network
services:
nxmeta:
image: docker.io/ptr727/nxmeta-lsio:latest
container_name: nxmeta
hostname: nxmeta
domainname: ${DOMAIN_NAME}
restart: unless-stopped
user: root
group_add:
- ${DOCKER_GROUP_ID}
security_opt: # Set with care
- seccomp=unconfined
- apparmor=unconfined
devices: # Pass through Intel/AMD iGPU for hardware accelerated video
- /dev/dri
environment:
- TZ=${TZ}
- PUID=${USER_NONROOT_ID} # Run as non-root user
- PGID=${USERS_GROUP_ID}
volumes: # ZFS volumes
- ${APPDATA_DIR}/nxmeta/config:/config
- ${NVR_DIR}/media:/media # ssdpool/nvr-media
- ${NVR_DIR}/backup:/backup # hddpool/nvr-backup
- ${NVR_DIR}/analytics:/analytics # ssdpool/nvr-analytics
tmpfs: # Keep mediaserver's Unix socket and tmp files in RAM
- /tmp:size=1g,mode=1777
networks:
public_network:
ipv4_address: ${NXMETA_IP} # Static IP
mac_address: ${NXMETA_MAC} # Static MAC
local_network:
stack_network:
labels:
- traefik.enable=true # Traefik SSL proxy
# Two-hostname pattern (DNS records configured externally, e.g.
# in your LAN DNS or hosts file): an A/AAAA `nxmeta -> ${NXMETA_IP}`
# points at the dedicated macvlan IP above for direct access,
# and a CNAME `nxmeta-web -> <traefik-host>` fronts the service
# with SSL termination. Traefik routes only the `-web` hostname;
# the bare hostname bypasses Traefik entirely.
- traefik.http.routers.nxmeta.rule=HostRegexp(`^nxmeta-web${DOMAIN_REGEX}$$`)
- traefik.http.services.nxmeta.loadbalancer.server.scheme=https
- traefik.http.services.nxmeta.loadbalancer.server.port=7001
The project supports the following product variants:
I ran DW Spectrum in my home lab on an Ubuntu Virtual Machine, and was looking for a way to run it in Docker. At the time Network Optix provided no support for Docker, but I did find the [The Home Repot NxWitness][thehomegithub-link] project, that inspired me to create this project.
I started with individual repositories for Nx Witness, Nx Meta, and DW Spectrum, but that soon became cumbersome with lots of duplication, and I combined all product flavors into this one project.
Today Network Optix supports [Docker][nxdocker-link], and they publish [build scripts][nxgithubdocker-link], but they do not publish container images.
The project creates two variants of each product using different base images:
The build pipeline also publishes internal base images (ptr727/nx-base:ubuntu-noble and
ptr727/nx-base-lsio:ubuntu-noble) built from ubuntu:noble and lsiobase/ubuntu:noble
to reduce CI cache churn. These base images are not intended for end-user deployments.
Note that smaller base images like [Alpine][alpine-link] are not [supported][nxossupport-link] by the mediaserver.
The [LinuxServer (LSIO)][lsio-link] base images provide valuable container functionality:
root-tool as root (required for license enforcement).${COMPANY_NAME} account, and the root-tool in a second instance under the root account, using a shared /tmp volume for socket IPC between the mediaserver and root-tool, but the user account ${COMPANY_NAME} does not readily map to a user on the host system.Images are published on [Docker Hub][hub-link]:
docker pull docker.io/ptr727/nxwitnessdocker pull docker.io/ptr727/nxwitness-lsiodocker pull docker.io/ptr727/nxmetadocker pull docker.io/ptr727/nxmeta-lsiodocker pull docker.io/ptr727/nxgodocker pull docker.io/ptr727/nxgo-lsiodocker pull docker.io/ptr727/dwspectrumdocker pull docker.io/ptr727/dwspectrum-lsiodocker pull docker.io/ptr727/wisenetwavedocker pull docker.io/ptr727/wisenetwave-lsioImages are tagged as follows:
latest: Latest published version, e.g. docker pull docker.io/ptr727/nxmeta:latest.stable: Latest released version, e.g. docker pull docker.io/ptr727/nxmeta:stable.rc: Latest RC version, e.g. docker pull docker.io/ptr727/nxmeta:rc.beta: Latest Beta version, e.g. docker pull docker.io/ptr727/nxmeta:betadevelop: Builds created from the develop branch, e.g. docker pull docker.io/ptr727/nxmeta:develop.develop-stable: The develop branch's stable build, e.g. docker pull docker.io/ptr727/nxmeta:develop-stable.develop-[version]: A develop build at a specific version, e.g. docker pull docker.io/ptr727/nxmeta:develop-6.1.3.43301.[version]: Release version number, e.g. docker pull docker.io/ptr727/nxmeta:5.2.2.37996.Notes:
latest and stable may be the same version if all builds are released builds.rc and beta tags are only built when Nx publishes RC and Beta builds. They may be older than the current latest or stable builds.main and picks up the latest upstream Ubuntu updates.main changing Make/Matrix.json publishes at once, so a new Nx version ships without waiting for the schedule. Only a push by the codegen App or Dependabot triggers this. A push by a person does not publish.develop tags are published by starting the publisher manually from develop.User accounts and directory names are based on the product variant exposed by the ${COMPANY_NAME} variable:
networkoptixdigitalwatchdognetworkoptix-metavmshanwhaThe LSIO images [re-link][init-nx-relocate] various internal paths to /config.
/config : Configuration files:
/opt/${COMPANY_NAME}/mediaserver/etc links to /config/etc : Configuration./root/.config/nx_ini links to /config/ini : Additional configuration./opt/${COMPANY_NAME}/mediaserver/var links to /config/var : State and logs./media : Recording files.The non-LSIO images must be mapped directly to the installed paths, refer to the [nxvms-docker][nxgithubvolumes-link] page for details.
/opt/${COMPANY_NAME}/mediaserver/etc : Configuration./home/${COMPANY_NAME}/.config/nx_ini : Additional configuration./opt/${COMPANY_NAME}/mediaserver/var : State and logs./media : Recording files.7001 : Default server port.PUID : User Id, LSIO only, optional.PGID : Group Id, LSIO only, optional.TZ : Timezone, e.g. America/Los_Angeles.See [LSIO docs][lsiopuid-link] for usage of PUID and PGID that allow the mediaserver to run under a user account and the root-tool to run as root.
Any network mode can be used, but due to the hardware bound licensing, host mode is [recommended][nxgithubnetworking-link].
docker create \
--name=nxwitness-lsio-test-container \
--hostname=nxwitness-lsio-test-host \
--domainname=foo.bar.net \
--restart=unless-stopped \
--network=host \
--env TZ=America/Los_Angeles \
--volume /mnt/nxwitness/config:/config:rw \
--volume /mnt/nxwitness/media:/media:rw \
docker.io/ptr727/nxwitness-lsio:stable
docker start nxwitness-lsio-test-container
services:
nxwitness:
image: docker.io/ptr727/nxwitness-lsio:stable
container_name: nxwitness-lsio-test-container
restart: unless-stopped
network_mode: host
environment:
# - PUID=65534 # id $user
# - PGID=65534 # id $group
- TZ=America/Los_Angeles
volumes:
- /mnt/nxwitness/config:/config
- /mnt/nxwitness/media:/media
tmpfs:
# Keep mediaserver's Unix socket and tmp files in RAM
- /tmp:size=1g,mode=1777
services:
nxwitness:
image: docker.io/ptr727/nxwitness:stable
container_name: nxwitness-test-container
restart: unless-stopped
network_mode: host
volumes:
- /mnt/nxwitness/config/etc:/opt/networkoptix/mediaserver/etc
- /mnt/nxwitness/config/nx_ini:/home/networkoptix/.config/nx_ini
- /mnt/nxwitness/config/var:/opt/networkoptix/mediaserver/var
- /mnt/nxwitness/media:/media
tmpfs:
# Keep mediaserver's Unix socket and tmp files in RAM
- /tmp:size=1g,mode=1777
https://github.com/ptr727/NxWitness/tree/main/Unraid to the "Template Repositories" section, at the bottom of the "Docker" configuration tab, and click "Save".RW/Slave access mode.nobody and users identifiers, PUID=99 and PGID=100.additionalLocalFsTypes advanced settings, see the [Missing Storage][missing-storage] section for help.mediaserver.conf [Configuration][configoptions-link]: https://[hostname]:[port]/#/server-documentationnx_vms_server.ini [Configuration][iniconfig-link]: https://[hostname]:[port]/api/iniConfig/https://[hostname]:[port]/#/settings/advancedhttps://[hostname]:[port]/#/health/storagesBuild overview:
CreateMatrix][create-matrix] is used to update available product versions, and to create Docker files for all product permutations.Version.json][version-json] is updated using the mediaserver [Releases JSON API][nxwitnessreleases-link] and [Packages API][packages-link].isBuildPublished()][isbuildpublished-link]. From the [Releases JSON API][nxwitnessreleases-link], release_date must be greater than 0 and release_delivery_days must be 0 or greater.Matrix.json][matrix-json] is created from the Version.json file and is used during pipeline builds using a [Matrix][matrix-link] strategy.NxMeta and NxMeta-LSIO ([test-pull-request.yml][test-pull-request-workflow]). The smoke build is gated on a change under Docker/, or to [Matrix.json][matrix-json] or [Version.json][version-json]. A version or matrix change is covered rather than skipped. The full matrix is not built on every PR.publish-release.yml][publish-release-workflow]). The weekly schedule publishes main. A manual dispatch publishes whichever branch it is started from, which is how develop is published.main that changes [Matrix.json][matrix-json] also publishes main, but only when the codegen App or Dependabot made it. A push by a person does not publish.main ships on the next weekly run, and a merge to develop ships only when someone dispatches the publisher from develop.CreateMatrix such that generic tags, e.g. latest, will never result in a lesser version number, i.e. break-fix-forward only, see [Issue #62][issue-62-link] for details on Nx re-publishing "released" builds using an older version breaking already upgraded systems.Local testing:
cd ./Make and [./Test.sh][test-sh], the following will be executed:
Create.sh][create-sh]: Creates the Dockerfiles and updates the latest version information using CreateMatrix.Build.sh][build-sh]: Builds the Dockerfiles using docker buildx build.Up.sh][up-sh]: Launch a Docker Compose stack [Test.yml][test-yml] to run all product variants.Clean.sh][clean-sh] to shutdown the compose stack and cleanup images.root-tool that is required to run as root.root-tool to run as root overly complicates running the mediaserver as a non-root user, and requires the container to run using host networking to not break the hardware license checks.nxvms-docker][nxgithubcompose-link] reference image [disabled root-tool in late 2025][nxvms-docker-roottool-link] by setting ignoreRootTool=true in mediaserver.conf and dropping their separate root-tool container. This trades hardware-ID license enforcement for a simpler unprivileged container. NxWitness does not follow this change, because licensed deployments would lose activation. This will be revisited only if Nx publishes a clearer official position on Docker licensing without root-tool.Nx MetaVMS Media directories are created on any discoverable writable storage..conf configuration files are located in a static mediaserver/etc location while .ini configuration files are in a user-account dependent location, e.g. /home/networkoptix/.config/nx_ini or /root/.config/nx_ini.mediaserver/etc.mediaserver/bin/plugins directory.mediaserver/bin/plugins directory is already pre-populated with Nx installed plugins.mediaserver/var/plugins or from sub-directories mounted below `mediaserver/bin/pluginContent type
Image
Digest
sha256:cb8eb1a00…
Size
441.8 MB
Last updated
3 days ago
docker pull ptr727/wisenetwave