ptr727/wisenetwave

By ptr727

Updated 5 days ago

This is a project to build and publish docker images for various Network Optix VMS products.

Buildkit cache
Image
Security
Content management system
0

10K+

ptr727/wisenetwave repository overview

Docker Projects for Network Optix VMS Products

This is a project to build and publish docker images for various [Network Optix][networkoptix-link] VMS products.

Build and Distribution

Build Status

[![Release Status][releasebuildstatus-shield]][actions-link]
[![Last Commit][lastcommit-shield]][github-link]

Release Notes

Version: 2.14:

Summary:

  • Fixed an LSIO permissions race where the startup 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

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

Table of Contents

Products

The project supports the following product variants:

  • [Network Optix][networkoptix-link] [Nx Witness VMS][nxwitness-link] (not available for purchase in the US)
  • [Network Optix][networkoptix-link] [Nx Meta VMS][nxmeta-link] (developer and early access version of Nx Witness)
  • [Network Optix][networkoptix-link] [Nx Go VMS][nxgo-link] (version of Nx Witness targeted at transportation sector)
  • [Digital Watchdog][digitalwatchdog-link] [DW Spectrum IPVMS][dwspectrum-link] (US licensed and OEM branded version of Nx Witness)
  • [Hanwha Vision][hanwhavision-link] [Wisenet WAVE VMS][dwspectrum-link] (US licensed and OEM branded version of Nx Witness)

Releases

Images are published on [Docker Hub][hub-link]:

  • [NxWitness][hubnxwitness-link]: docker pull docker.io/ptr727/nxwitness
  • [NxWitness-LSIO][hubnxwitnesslsio-link]: docker pull docker.io/ptr727/nxwitness-lsio
  • [NxMeta][hubnxmeta-link]: docker pull docker.io/ptr727/nxmeta
  • [NxMeta-LSIO][hubnxmetalsio-link]: docker pull docker.io/ptr727/nxmeta-lsio
  • [NxGo][hubnxgo-link]: docker pull docker.io/ptr727/nxgo
  • [NxGo-LSIO][hubnxwitnesslsio-link]: docker pull docker.io/ptr727/nxgo-lsio
  • [DWSpectrum][hubdwspectrum-link]: docker pull docker.io/ptr727/dwspectrum
  • [DWSpectrum-LSIO][hubdwspectrumlsio-link]: docker pull docker.io/ptr727/dwspectrum-lsio
  • [WisenetWAVE][hubwisenetwave-link]: docker pull docker.io/ptr727/wisenetwave
  • [WisenetWAVE-LSIO][hubwisenetwavelsio-link]: docker pull docker.io/ptr727/wisenetwave-lsio

Images 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:beta
  • develop: 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.
  • Images are published once a week on a schedule (and on-demand via manual trigger), picking up the latest upstream Ubuntu updates and newly released Nx product versions. A single scheduled run publishes both the 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.
  • See Build Process for more details.

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]

Overview

Introduction

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.

Base Images

The project creates two variants of each product using different base images:

  • [Ubuntu][ubuntu-link] using [ubuntu:noble][ubuntudocker-link] base image.
  • [LinuxServer][lsio-link] using [lsiobase/ubuntu:noble][ubuntulsiodocker-link] base image.

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.

LinuxServer

The [LinuxServer (LSIO)][lsio-link] base images provide valuable container functionality:

  • The LSIO images are based on [s6-overlay][s6overlay-link], are updated weekly, and LSIO [produces][lsiofleet-link] containers for many popular open source applications.
  • LSIO allows us to [specify][lsiopuid-link] the user account to use when running the mediaserver, while still running the root-tool as root (required for license enforcement).
  • Running as non-root is a [best practice][dockernonroot-link], and required if we need user specific permissions when accessing mapped volumes.
  • The [nxvms-docker][nxgithubcompose-link] project takes a different approach running a compose stack that runs the mediaserver in one instance under the ${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.

Configuration

User accounts and directory names are based on the product variant exposed by the ${COMPANY_NAME} variable:

  • NxWitness: networkoptix
  • DWSpectrum: digitalwatchdog
  • NxMeta: networkoptix-metavms
  • WisenetWAVE: hanwha
LSIO Volumes

The 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.
Non-LSIO Volumes

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.
Ports
  • 7001 : Default server port.
Environment Variables
  • 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.

Network Mode

Any network mode can be used, but due to the hardware bound licensing, host mode is [recommended][nxgithubnetworking-link].

Examples

LSIO Docker Create
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
LSIO Docker Compose
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
Non-LSIO Docker Compose
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
Unraid Template
  • Add the template URL https://github.com/ptr727/NxWitness/tree/main/Unraid to the "Template Repositories" section, at the bottom of the "Docker" configuration tab, and click "Save".
  • Create a new container by clicking the "Add Container" button, select the desired product template from the dropdown.
  • If using Unassigned Devices for media storage, use RW/Slave access mode.
  • Use nobody and users identifiers, PUID=99 and PGID=100.
  • Register the Unraid filesystems in the additionalLocalFsTypes advanced settings, see the Missing Storage section for help.

Product Information

Release Information
  • Nx Witness:
    • [Releases JSON API][nxwitnessreleases-link]
    • [Downloads][nxwitnessdownload-link]
    • [Beta Downloads][nxwitnessbetadownload-link]
    • [Release Notes][nxwitnessreleasenotes-link]
  • Nx Meta:
    • [Releases JSON API][nxmetareleases-link]
    • [Signup for Nx Meta][getstartedwithmeta-link]
    • [Request Developer Licenses][getalicense-link]
    • [Downloads][nxmetadownload-link]
    • [Beta Downloads][nxmetabetadownload-link]
  • Nx Go:
    • [Releases JSON API][nxgoreleases-link]
    • [Downloads][nxgodownload-link]
    • [Beta Downloads][nxgobetadownload-link]
    • [Release Notes][nxgoreleasenotes-link]
  • DW Spectrum:
    • [Releases JSON API][dwspectrumreleases-link]
    • [Downloads][dwspectrumdownload-link]
    • [Release Notes][dwspectrumreleasenotes-link]
  • Wisenet WAVE:
    • [Releases JSON API][wisenetwavereleases-link]
    • [Downloads][wisenetwavedownload-link]
    • [Release Notes][wisenetwavereleasenotes-link]
Advanced Configuration
  • mediaserver.conf [Configuration][configoptions-link]: https://[hostname]:[port]/#/server-documentation
  • nx_vms_server.ini [Configuration][iniconfig-link]: https://[hostname]:[port]/api/iniConfig/
  • Advanced Server Configuration: https://[hostname]:[port]/#/settings/advanced
  • Storage Reporting: https://[hostname]:[port]/#/health/storages

Build Process

Build 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].
  • The logic follows the same pattern as used by the [Nx Open][releaseinfo-link] desktop client logic.
  • The "released" status of a build follows the same method as Nx uses in [isBuildPublished()][isbuildpublished-link] where release_date and release_delivery_days from the [Releases JSON API][nxwitnessreleases-link] must be greater than 0
  • Matrix.json is created from the Version.json file and is used during pipeline builds using a [Matrix][matrix-link] strategy.
  • Automated builds use GitHub Actions:
    • Pull requests run unit tests, and when image files change, a fast representative amd64 smoke build of NxMeta and NxMeta-LSIO (test-pull-request.yml) -- the full matrix is not built on every PR.
    • Publishing happens only on a weekly schedule or manual trigger (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.
  • Version history is maintained and used by 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:

  • Run 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.
  • Ctrl-Click on the links to launch the web UI for each of the product variants.
  • Run Clean.sh to shutdown the compose stack and cleanup images.

Known Issues

  • Licensing:
    • Camera recording license keys are activated and bound to hardware attributes of the host server collected by the root-tool that is required to run as root.
    • Requiring the 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.
    • Docker containers are supposed to be portable, and moving containers between hosts will break license activation.
    • Nx's own [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 to fix: Associate licenses with the [Cloud Account][nxcloud-link] not the local hardware.
  • Storage Management:
    • The mediaserver attempts to automatically decide what storage to use.
    • Filesystem types are filtered out if not on the [supported list][nxgithubstorage-link].
    • Mounted volumes are ignored if backed by the same physical storage, even if logically separate.
    • Unwanted Nx MetaVMS Media directories are created on any discoverable writable storage.
    • Nx to fix: Eliminate the elaborate filesystem filter logic and use only the admin specified storage locations.
  • Configuration Files:
    • .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.
    • There is no value in having a server use per-user configuration directories, and it is inconsistent to mix configuration file locations.
    • Nx to fix: Store all configuration files in mediaserver/etc.
  • External Plugins:
    • Custom or [Marketplace][nxmarketplace-link] plugins are installed in the mediaserver/bin/plugins directory.
    • The mediaserver/bin/plugins directory is already pre-populated with Nx installed plugins.
    • It is not possible to use external plugins from a mounted volume as the directory is already in-use.
    • Nx to fix: Load plugins from mediaserver/var/plugins or from sub-directories mounted below mediaserver/bin/plugins, e.g. mediaserver/bin/plugins/external
  • Lifetime Upgrades:
    • Nx is a cloud product, free to view, free upgrades, comes with ongoing costs of hosting, maintenance, and support, it is [unfeasible][nxcrunchbase-link] to sustain a business with ongoing costs using perpetual one-off licenses.
    • My personal experience with [Digital Watchdog][digitalwatchdog-link] and their [Lifetime Upgrades and No Annual Agreements][dwupgrades-link] is an inflexible policy of three activations per license and you have to buy a new license, thus the "license lifetime" is a multiplier of the "hardware lifetime".
    • Nx to fix: Yearly camera license renewals covering the cost of support and upgrades.
  • Archiving:
    • Nx makes no distinction between recording and archiving storage, archive is basically just a recording mirror without any capacity or retention benefit.
    • Recording storage is typically high speed low latency high cost low capacity SSD/NVMe arrays, while archival playback storage is very high capacity low cost magnetic media arrays.
    • Nx to fix: Implement something akin to archiving in [Milestone XProtect VMS][milestone-link] where reco

Tag summary

Content type

Image

Digest

sha256:a522bb380

Size

441.9 MB

Last updated

5 days ago

docker pull ptr727/wisenetwave:stable