Deployment

Last validated: 2026-05-05

Use this checklist when moving an Oden setup from commissioning to unattended or production use. It focuses on the parts that must survive restarts: the Streamer service, the Streamer project file, Player display behavior, licenses, network reachability, and startup verification.

Streamer service

On Linux vehicle computers, Oden Fleet Streamer can install a systemd service named oden-streamer.service. The service is not installed by default. During package installation, choose to install, enable, and start the service when the Streamer should run automatically on boot.

For scripted Linux deployments, pre-seed the installer answers before installing the Fleet Streamer package:

Install Oden Fleet Streamer with the service enabled
echo "oden-streamer oden-streamer/accept-eula boolean true" | sudo debconf-set-selections
echo "oden-streamer oden-streamer/install-services boolean true" | sudo debconf-set-selections
export DEBIAN_FRONTEND=noninteractive
sudo apt-get install ./oden-fleet-streamer_*.deb

The service runs as root, uses /opt/oden-streamer as its working directory, and starts:

/usr/bin/oden-streamer --headless /opt/oden-streamer/oden-vehicle-config.vproj

Use systemctl for normal service operations:

sudo systemctl status oden-streamer.service
sudo systemctl start oden-streamer.service
sudo systemctl stop oden-streamer.service
sudo systemctl restart oden-streamer.service
sudo systemctl enable oden-streamer.service
sudo systemctl disable oden-streamer.service
--headless is a Linux Streamer mode where the GUI is not rendered. It is intended for unattended vehicle computers and embedded platforms.

If you need remote access to the Streamer GUI while output is stopped, start the Streamer with --configurator as well, or make that part of the deployment’s service definition. See Projects and Scenes for the Player-side Streamer Configurator workflow.

Do not start a second Streamer on the same computer while the service is running. Stop oden-streamer.service before opening the same project in the local GUI.

Streamer project file

The Fleet Streamer service loads /opt/oden-streamer/oden-vehicle-config.vproj. If that file does not exist when the service starts, the service copies /opt/oden-streamer/oden-vehicle-config-default.vproj to that path before launching Streamer.

Keep the production vehicle project at:

/opt/oden-streamer/oden-vehicle-config.vproj

To edit the project on the vehicle computer:

  1. Stop the service.

  2. Open the project with elevated permissions.

  3. Save the project.

  4. Close Streamer.

  5. Start the service again.

sudo systemctl stop oden-streamer.service
sudo oden-streamer /opt/oden-streamer/oden-vehicle-config.vproj
sudo systemctl start oden-streamer.service

The project may be owned by root because the service runs as root. If you open it as a normal user, saving may fail.

Prefer changing the project through the Streamer GUI or Streamer Configurator. Editing the .vproj file directly is possible because it is a libconfig file, but it is easy to break a production project with an invalid edit.

Before deploying the project, confirm at least:

  • The correct Startup Scene is selected in Project Settings.

  • All camera inputs start reliably after a cold boot.

  • The Streamer Output settings match the target resolution, codec, bitrate, FEC, and bandwidth-control policy.

  • Any project plugins are deployed beside the project or in the configured Project Plugins Path.

Player display setup

For operator stations, configure the Player so the operator sees the intended view without commissioning controls.

Set these in Application Settings on the Player:

Hide GUI on Startup

Enable when the Player should start with the GUI hidden.

Inhibit Mouse Look

Enable when mouse movement must not move the 3D camera.

Window Mode

Choose the production display mode. Use Fullscreen for lowest latency on one display, Windowed Fullscreen when the window should stay visible while another screen is clicked, or Spanning Fullscreen for a multi-display span.

Only Show Exit Dialog

Enable if operators should see only the exit dialog while the GUI is hidden.

The same settings can be deployed through the application config file:

Windows

%LOCALAPPDATA%\oden\oden.conf

Linux

$HOME/.config/oden/oden.conf

Player config values
hide_gui : true;
inhibit_mouse_look : true;
window_mode : "fullscreen";

Use "windowed_fullscreen" or "spanning_fullscreen" instead of "fullscreen" when that better matches the display layout.

The GUI can still be toggled with the configured Toggle Hide GUI keyboard shortcut. The default shortcut is Ctrl+H.

The --windowless command-line flag hides the Player window itself. Use it only for deployments where the Player must run without a visible application window. The windowless mode can be toggled with Ctrl+Shift+H.

HMD and VR display setup

When the Player is used with a head-mounted display, configure HMD behavior before hiding the GUI for production. Tested HMD families include Valve Index, HP Reverb G1/G2, and HTC Vive Pro 1/2. Other OpenVR/OpenXR-compatible headsets may work, but should be validated with the production GPU, driver, and runtime.

Key settings:

HMD Selection

Selects the runtime backend: Any, Oculus, OpenVR, OpenXR, or None. Use None to disable HMD output and Any only when the deployment does not need a fixed backend.

Fixed Position

Locks HMD position to the origin and disables XYZ movement in the HMD world.

Fps Cam Track HMD

Makes the monitor view match what the HMD user sees.

Draw Background

Shows the Oden background in the HMD.

Draw While Inactive

Keeps rendering to the HMD even when the headset is not currently worn.

Draw To Screen

Disable screen rendering when only the HMD output is needed and GPU load must be reduced.

Avoid changing HMD field-of-view factors unless Voysys support has asked for it. Non-default FoV can cause operator discomfort and invalidates display validation.

For controller-based plugins, test controller remapping on the exact HMD model. Button and axis IDs can differ between runtimes and controller generations.

Licenses

Activate each installed Oden application on the computer where it will run before production use. Activation requires internet access and binds the license to that computer. After activation, Oden can run offline until the local activation period needs to be refreshed.

For headless Streamer service installations, activate with the same Linux command that the service uses, then restart the service:

sudo oden-streamer --activate <license-key>
sudo systemctl restart oden-streamer.service

For Player deployments, activate the installed Player application:

oden-vr --activate <license-key>

On Windows, run the installed executable from PowerShell:

& "C:\Program Files\OdenVR\OdenVR.exe" --activate <license-key>
& "C:\Program Files\Oden Streamer\OdenStreamer.exe" --activate <license-key>

Before moving a license to another computer, revoke it while the old computer still has internet access:

oden-vr --revoke
oden-streamer --revoke

Check Help  License Info during acceptance testing and record the activation status for each production computer. For license file locations and offline behavior, see Activate Licenses and Projects and Scenes.

Network readiness

Verify the production network from the direction Oden will actually connect. By default, the Streamer initiates the connection and the Player responds, so the Player receive port must be reachable from the Streamer.

Check these items before unattended operation:

  • The Player Remote Streamer entity has the correct link mode, receive port, and bind settings.

  • The Streamer network settings point at the Player responder address and port, or at the configured relay path.

  • Firewalls allow the Oden traffic on the configured ports.

  • If a Linux link uses Bind Device, the named network interface exists after boot and is the intended route.

  • If WireGuard encryption or relay routing is used, Internal Src and Internal Dst match the tunnel addresses.

  • Target Bitrate, Target usage, FEC, and reorder settings leave headroom for the real link.

  • Link stats show stable bandwidth, round-trip time, and packet loss under realistic load.

Use the Player Remote Streamer stats during tests. Packet Loss should stay near zero on a clean link, Round Trip Time should match the expected path, and Bandwidth should stay within the available network budget.

Docker Streamer deployments

Use Docker only when the deployment needs container isolation or a containerized vehicle runtime. Native package installation and oden-streamer.service are simpler for most vehicles.

Prerequisites:

  • NVIDIA GPU

  • Docker

  • NVIDIA Container Toolkit

On Ubuntu, install and configure NVIDIA Container Toolkit:

curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
  sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker

For desktop Ubuntu containers, use an Ubuntu base image matching the Oden .deb package target. For Jetson, use an L4T base image matching the host JetPack version. Check Jetson L4T with cat /etc/nv_tegra_release.

On desktop NVIDIA systems, the container image does not need to include the host NVIDIA driver libraries. NVIDIA Container Toolkit injects the matching driver libraries at runtime when the container is started with GPU access. That is why a plain Ubuntu base image can be enough for desktop Oden Streamer containers, as long as the Ubuntu package target matches the image.

Desktop Ubuntu Dockerfile
FROM ubuntu:24.04

ARG ODEN_INSTALLER_PATH=./oden-streamer.deb
ENV DEBIAN_FRONTEND=noninteractive

COPY "$ODEN_INSTALLER_PATH" /oden-streamer.deb
RUN apt-get update -qq && \
    apt-get install -qq -y --no-install-recommends /oden-streamer.deb && \
    rm -rf /var/lib/apt/lists/* /oden-streamer.deb

USER root
CMD [ "oden-streamer", "--headless", "--configurator", "/root/project/streamer.vproj" ]

For Jetson containers, use the matching L4T base image:

Jetson Dockerfile
FROM nvcr.io/nvidia/l4t-base:36.4.0

ARG ODEN_INSTALLER_PATH=./oden-streamer.deb
ENV DEBIAN_FRONTEND=noninteractive

COPY "$ODEN_INSTALLER_PATH" /oden-streamer.deb
RUN apt-get update -qq && \
    apt-get install -qq -y --no-install-recommends /oden-streamer.deb && \
    rm -rf /var/lib/apt/lists/* /oden-streamer.deb

USER root
CMD [ "oden-streamer", "--headless", "--configurator", "/root/project/streamer.vproj" ]

JetPack 5.1 uses nvcr.io/nvidia/l4t-base:35.3.1. JetPack 6.1 uses nvcr.io/nvidia/l4t-base:36.4.0.

Build with the Oden Streamer .deb next to the Dockerfile:

docker build --build-arg ODEN_INSTALLER_PATH=./oden-streamer.deb -t oden-streamer:latest .

Run with GPU access, host networking, license data, and the project directory mounted:

docker run --runtime nvidia -e NVIDIA_VISIBLE_DEVICES=all \
  --network host --rm -it \
  -v /run/udev:/run/udev:ro \
  -v ./key.conf:/root/.config/oden/Oden_Streamer/key.conf \
  -v ./project:/root/project \
  oden-streamer:latest

--network host is commonly used because Oden uses realtime UDP links. Mount camera devices and plugin folders explicitly when the project needs them. --runtime nvidia and NVIDIA_VISIBLE_DEVICES=all give the Streamer GPU access; on newer Docker installations, --gpus all can be used instead. The /run/udev mount lets Oden read hardware identity data used by licensing. Mount key.conf at /root/.config/oden/Oden_Streamer/key.conf when the Streamer runs as root in the container, and mount the project directory at the same path used by the Dockerfile CMD. In the example above, the project file must be available as /root/project/streamer.vproj.

Docker Compose
services:
  oden-streamer:
    image: oden-streamer:latest
    network_mode: host
    volumes:
      - /run/udev:/run/udev:ro
      - ./key.conf:/root/.config/oden/Oden_Streamer/key.conf
      - ./project:/root/project
    environment:
      - NVIDIA_VISIBLE_DEVICES=all
    runtime: nvidia
docker compose up

For Jetson zero-copy GStreamer IPC, make sure the nvunixfd plugin is available inside the container by installing it in the image or mounting it from the host. On JetPack 5, the Streamer installer bundles the plugin in /usr/lib/aarch64-linux-gnu/gstreamer-1.0/. On JetPack 6 and newer, install DeepStream or build it from https://github.com/voysys/nvunixfd with make, then copy the .so to /usr/lib/aarch64-linux-gnu/gstreamer-1.0/. For container deployments, repeat that install inside the image or mount the plugin into the same path.

Startup checks

Run these checks after every production image, package upgrade, project update, or network change.

Streamer service and project
sudo systemctl status oden-streamer.service
test -f /opt/oden-streamer/oden-vehicle-config.vproj
Streamer logs
sudo journalctl -u oden-streamer.service -b --no-pager

Confirm that:

  • The service is active (running) after boot.

  • The expected project file was loaded.

  • No license error is shown.

  • All cameras or test sources start.

  • Output starts with the expected codec, resolution, frame rate, and bitrate.

  • The Player connects without manual steps.

  • The Player GUI is hidden or visible according to the deployment profile.

  • Remote Streamer stats show expected bandwidth, round-trip time, and packet loss.

  • Control, audio, plugins, and external integrations are active if the deployment uses them.

Finally, power-cycle the vehicle computer and the operator station. Do not sign off the deployment until the complete stream, control path, and display layout recover without manual commissioning steps.