This is a project to build and publish docker images for various Network Optix VMS products.
10K+
This is a project to build and publish docker images for various [Network Optix][networkoptix-link] VMS products.
[![Release Status][releasebuildstatus-shield]][actions-link]
[![Last Commit][lastcommit-shield]][github-link]
Version: 2.14:
Summary:
chown could run before the PUID/PGID remap, leaving /config and /media owned by the wrong user and breaking media writes.See Release 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:
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.[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 RC and Beta builds are published by Nx, and may be older than current latest or stable builds.main tags (latest, stable, version numbers) and the develop tags. Merging code or dependency updates does not republish images, so the published images only change when there is an actual content change.Docker releases:
[NxWitness][hubnxwitness-link]:
[![NxWitness Stable][hubnxwitnessstable-shield]][hubnxwitness-link]
[![NxWitness Latest][hubnxwitnesslatest-shield]][hubnxwitness-link]
[![NxWitness RC][hubnxwitnessrc-shield]][hubnxwitness-link]
[![NxWitness Beta][hubnxwitnessbeta-shield]][hubnxwitness-link]
[NxWitness-LSIO][hubnxwitnesslsio-link]:
[![NxWitness-LSIO Stable][hubnxwitnesslsiostable-shield]][hubnxwitnesslsio-link]
[![NxWitness-LSIO Latest][hubnxwitnesslsiolatest-shield]][hubnxwitnesslsio-link]
[![NxWitness-LSIO RC][hubnxwitnesslsiorc-shield]][hubnxwitnesslsio-link]
[![NxWitness-LSIO Beta][hubnxwitnesslsiobeta-shield]][hubnxwitnesslsio-link]
[NxMeta][hubnxmeta-link]:
[![NxMeta Stable][hubnxmetastable-shield]][hubnxmeta-link]
[![NxMeta Latest][hubnxmetalatest-shield]][hubnxmeta-link]
[![NxMeta RC][hubnxmetarc-shield]][hubnxmeta-link]
[![NxMeta Beta][hubnxmetabeta-shield]][hubnxmeta-link]
[NxMeta-LSIO][hubnxmetalsio-link]:
[![NxMeta-LSIO Stable][hubnxmetalsiostable-shield]][hubnxmetalsio-link]
[![NxMeta-LSIO Latest][hubnxmetalsiolatest-shield]][hubnxmetalsio-link]
[![NxMeta-LSIO RC][hubnxmetalsiorc-shield]][hubnxmetalsio-link]
[![NxMeta-LSIO Beta][hubnxmetalsiobeta-shield]][hubnxmetalsio-link]
[NxGo][hubnxgo-link]:
[![NxGo Stable][hubnxgostable-shield]][hubnxgo-link]
[![NxGo Latest][hubnxgolatest-shield]][hubnxgo-link]
[![NxGo RC][hubnxgorc-shield]][hubnxgo-link]
[![NxGo Beta][hubnxgobeta-shield]][hubnxgo-link]
[NxGo-LSIO][hubnxgolsio-link]:
[![NxGo-LSIO Stable][hubnxgolsiostable-shield]][hubnxgolsio-link]
[![NxGo-LSIO Latest][hubnxgolsiolatest-shield]][hubnxgolsio-link]
[![NxGo-LSIO RC][hubnxgolsiorc-shield]][hubnxgolsio-link]
[![NxGo-LSIO Beta][hubnxgolsiobeta-shield]][hubnxgolsio-link]
[DWSpectrum][hubdwspectrum-link]:
[![DWSpectrum Stable][hubdwspectrumstable-shield]][hubdwspectrum-link]
[![DWSpectrum Latest][hubdwspectrumlatest-shield]][hubdwspectrum-link]
[![DWSpectrum RC][hubdwspectrumrc-shield]][hubdwspectrum-link]
[![DWSpectrum Beta][hubdwspectrumbeta-shield]][hubdwspectrum-link]
[DWSpectrum-LSIO][hubdwspectrumlsio-link]:
[![DWSpectrum-LSIO Stable][hubdwspectrumlsiostable-shield]][hubdwspectrumlsio-link]
[![DWSpectrum-LSIO Latest][hubdwspectrumlsiolatest-shield]][hubdwspectrumlsio-link]
[![DWSpectrum-LSIO RC][hubdwspectrumlsiorc-shield]][hubdwspectrumlsio-link]
[![DWSpectrum-LSIO Beta][hubdwspectrumlsiobeta-shield]][hubdwspectrumlsio-link]
[WisenetWAVE][hubwisenetwave-link]:
[![WisenetWAVE Stable][hubwisenetwavestable-shield]][hubwisenetwave-link]
[![WisenetWAVE Latest][hubwisenetwavelatest-shield]][hubwisenetwave-link]
[![WisenetWAVE RC][hubwisenetwaverc-shield]][hubwisenetwave-link]
[![WisenetWAVE Beta][hubwisenetwavebeta-shield]][hubwisenetwave-link]
[WisenetWAVE-LSIO][hubwisenetwavelsio-link]:
[![WisenetWAVE-LSIO Stable][hubwisenetwavelsiostable-shield]][hubwisenetwavelsio-link]
[![WisenetWAVE-LSIO Latest][hubwisenetwavelsiolatest-shield]][hubwisenetwavelsio-link]
[![WisenetWAVE-LSIO RC][hubwisenetwavelsiorc-shield]][hubwisenetwavelsio-link]
[![WisenetWAVE-LSIO Beta][hubwisenetwavelsiobeta-shield]][hubwisenetwavelsio-link]
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.User accounts and directory names are based on the product variant exposed by the ${COMPANY_NAME} variable:
networkoptixdigitalwatchdognetworkoptix-metavmshanwhaThe LSIO images re-link 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 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 is used to update available product versions, and to create Docker files for all product permutations.Version.json is updated using the mediaserver [Releases JSON API][nxwitnessreleases-link] and [Packages API][packages-link].isBuildPublished()][isbuildpublished-link] where release_date and release_delivery_days from the [Releases JSON API][nxwitnessreleases-link] must be greater than 0Matrix.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) -- the full matrix is not built on every PR.publish-release.yml), which builds and pushes the full matrix for both the main and develop branches. Merges to main/develop (including auto-merged Dependabot and codegen updates) do not publish; the next scheduled run picks them up.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 for details on Nx re-publishing "released" builds using an older version breaking already upgraded systems.Local testing:
cd ./Make and ./Test.sh, the following will be executed:
Create.sh: Create Dockerfile's and update the latest version information using CreateMatrix.Build.sh: Builds the Dockerfile's using docker buildx build.Up.sh: Launch a docker compose stack Test.yaml to run all product variants.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 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 - licensed deployments would lose activation - and will revisit 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/plugins, e.g. mediaserver/bin/plugins/externalContent type
Image
Digest
sha256:4ef192000…
Size
484.9 MB
Last updated
5 days ago
docker pull ptr727/dwspectrum-lsio