---
title: Bring Zenoh to ROS 2 with snaps
description: Deploy Zenoh with ROS 2 using snaps. Learn approaches including packaging,
  routers, and integration bridges for stable and secure robotics.
url: https://canonical.com/blog/bring-zenoh-to-ros-2-with-snaps?format=md
---

1. [Blog](https://canonical.com/blog)
2. Article

---

[gbeuzeboc](https://canonical.com/blog/author/gbeuzeboc "More about gbeuzeboc")

15 September 2026

# Bring Zenoh to ROS 2 with snaps

[ROS 2](https://canonical.com/blog/tag/ros-2)
[Snap](https://canonical.com/blog/tag/snap)

---

Share the article

ROS 2 gives robotics developers the freedom to choose the middleware that fits their system. As a communication protocol for ROS, Zenoh has gained strong traction. It delivers proven performance and stability while giving developers explicit control over node discovery.

Zenoh is a lightweight, high-performance communication protocol designed for robotics and distributed systems. Supporting publisher/subscriber and query-based communication, it handles unreliable network connections efficiently. It can act as the middleware for ROS 2 systems.

For teams running ROS 2 applications with DDS (Data Distribution Service), a Zenoh bridge provides a way to keep applications as they are and bridge their communication into Zenoh. Meanwhile, the Zenoh router provides data stream routes and distributes queries across endpoints.

To deploy ROS 2 and Zenoh effectively, you need a stable, reliable environment. This blog explores how to achieve that using snaps, covering three key deployment approaches:

* **Packaging:** Include the Zenoh ROS middleware directly within your application
* **Infrastructure:** Run the Zenoh router as a standalone snap
* **Integration:** Use the Zenoh-to-DDS bridge to connect existing ROS 2 applications

These methods are not mutually exclusive, enabling teams to mix and match as needed to suit their architecture.

## **Package Zenoh with your ROS 2 application**

When developers want to use Zenoh as part of the application, they can include the rmw\_zenoh\_cpp dependency directly in the ROS 2 [`snapcraft.yaml`](https://ubuntu.com/docs/snapcraft/latest/reference/snapcraft-yaml/).

The [talker\_listener\_zenoh\_core24](https://github.com/ubuntu-robotics/ros-snaps-examples/tree/main/talker_listener_zenoh_core24) project in the ROS snap examples repository demonstrates this approach with ROS 2 Jazzy. It packages the familiar `demo_nodes_cpp` talker and listener while selecting Zenoh via the `RMW_IMPLEMENTATION` environment variable.

The important changes in `snapcraft.yaml` appear below:

```
base: core24
confinement: strict

parts:
  ros-demos:
    plugin: colcon
    source: https://github.com/ros2/demos.git
    source-branch: jazzy
    stage-packages:
      - ros-jazzy-rmw-zenoh-cpp
      - ros-jazzy-ros2run

apps:
  talker-router:
    command: opt/ros/jazzy/bin/ros2 run demo_nodes_cpp talker
    plugs: [network, network-bind]
    extensions: [ros2-jazzy]
    environment:
      RMW_IMPLEMENTATION: rmw_zenoh_cpp
```

The [`ros2-jazzy extension`](https://snapcraft.io/docs/robotics/) sets up the ROS 2 environment inside the snap. The `stage-packages` entry adds `rmw_zenoh_cpp`, while `RMW_IMPLEMENTATION` tells the application to use it at runtime.

This keeps the communication choice within the application. The developer controls the ROS 2 version, middleware package, environment, and application lifecycle in one artifact. The same tested package can then move between development systems and robots without rebuilding on each device.

The [example](https://github.com/ubuntu-robotics/ros-snaps-examples/blob/main/talker_listener_zenoh_core24/snap/snapcraft.yaml) provides two operating modes: one using a dedicated Zenoh router (talker-router/listener-router) and another relying on multicast scouting (talker/listener). This flexibility enables developers to start with a compact, all-in-one package for workstations or robots, then evolve to a separate router service if their communication architecture scales, without needing to change the application.

## **Run the Zenoh router as a snap**

A router is infrastructure, and infrastructure requires stability.

The [zenohd snap](https://snapcraft.io/zenohd) packages the Zenoh router as a command and a system service. It can be installed independently of the ROS 2 applications that use it:

```
sudo snap install zenohd
sudo snap start --enable zenohd.daemon
```

The service is installed disabled, so users decide when to enable it. Once enabled, snapd manages it like other snap services.

The router can also run as a terminal command:

```
zenohd [OPTIONS]
```

If you plan to pass a configuration file via the CLI, ensure it is in a [location accessible to a strictly confined snap](https://snapcraft.io/docs/reference/administration/data-locations/#user-data).

The snap looks for a JSON5 or YAML configuration under its snap-managed data directories. The default daemon configuration path is:

```
/var/snap/zenohd/common/config.json5
```

The [upstream reference configuration](https://github.com/eclipse-zenoh/zenoh/blob/main/DEFAULT_CONFIG.json5) documents the available options.

After changing it, restart the service:

```
sudo snap restart zenohd.daemon
```

The [`snapcraft.yaml`](https://github.com/canonical/zenohd-snap) file describes the daemon and command for reference.

With a router deployed in the cloud, multiple Zenoh-enabled applications can communicate across the internet. In that setup, consider configuring [TLS authentication for Zenoh](https://zenoh.io/docs/manual/tls/).

## **Add Zenoh to existing ROS 2 applications**

Repackaging an application is not always the right starting point. A robot may already run several ROS 2 nodes using DDS, or a team may want to introduce Zenoh without changing those nodes.

The [zenoh-bridge-ros2dds snap](https://snapcraft.io/zenoh-bridge-ros2dds) packages the upstream Zenoh bridge for ROS 2 over DDS. The bridge discovers ROS 2 communication on its DDS side and maps it to Zenoh. This lets existing ROS 2 applications keep their current middleware configuration.

Install and enable it with:

```
sudo snap install zenoh-bridge-ros2dds
sudo snap start --enable zenoh-bridge-ros2dds.bridge
```

Like the router snap, the bridge is installed disabled and can also run as a CLI:

```
zenoh-bridge-ros2dds [OPTIONS]
```

Its configuration can live in the snap’s common data directory:

```
/var/snap/zenoh-bridge-ros2dds/common/config.json5
```

Or in the root user data directory

```
/root/snap/zenoh-bridge-ros2dds/common/config.json5
```

The [upstream reference configuration](https://github.com/eclipse-zenoh/zenoh-plugin-ros2dds/blob/main/DEFAULT_CONFIG.json5) documents the available options.

The bridge can sit beside a ROS 2 system on a robot, workstation or other host and connect that DDS domain to the Zenoh side of the architecture. ROS 2 nodes do not need to know that the bridge is there.

The [`snapcraft.yaml`](https://github.com/canonical/zenoh-bridge-ros2dds-snap) file demonstrates how to package the Rust-based bridge as both a daemon and a CLI.

## **One RMW implementation, three approaches**

To recap, Zenoh offers flexible deployment options for ROS 2 systems through three distinct approaches using snaps:

* **Packaging:** Developers can bundle the `rmw_zenoh_cpp` RMW implementation directly within their application snap.
* **Infrastructure:** The `zenohd` router snap serves as shared infrastructure for routing data streams across the system.
* **Integration:** The `zenoh-bridge-ros2dds` snap bridges existing DDS-based applications into the Zenoh network without requiring code changes.

Snaps unify these deployments with a consistent operational model. All three approaches support `amd64` and `arm64` platforms, ensuring hardware-agnostic deployment across different robots. Furthermore, snaps provide a single framework for transactional updates, lifecycle management, and service control through `snapd`.

Security is central to this model. Strict confinement isolates the communication stack, while mandatory interfaces like `network` and `network-bind` enforce explicit system access. This ensures that each component operates within a well-defined boundary.

Ultimately, this allows the application, the bridge, and the router to evolve independently with their own configuration and refresh cycles. This modularity maintains a robust operational boundary for the entire robotics architecture.

## **Start snapping Zenoh into ROS 2**

Here are some practical starting points for the three projects:

* Explore the [`rmw_zenoh_cpp` talker and listener example](https://github.com/ubuntu-robotics/ros-snaps-examples/tree/main/talker_listener_zenoh_core24)
* Install the [`zenohd` router snap](https://snapcraft.io/zenohd)
* Install the [`zenoh-bridge-ros2dds` snap](https://snapcraft.io/zenoh-bridge-ros2dds)
* Check the [`zenohd` snap source](https://github.com/canonical/zenohd-snap)
* Check the [`zenoh-bridge-ros2dds` snap source](https://github.com/canonical/zenoh-bridge-ros2dds-snap)

If snaps are new to you, start with the [Snapcraft overview](https://snapcraft.io/docs/snapcraft-overview/), then [set up Snapcraft](https://snapcraft.io/docs/snapcraft-setup/) and follow the guide to [create a snap](https://snapcraft.io/docs/create-a-new-snap/). The [Snapcraft robotics documentation](https://snapcraft.io/docs/robotics/) covers the ROS-specific extensions and workflows.

For the middleware itself, consult the [ROS 2 Jazzy guide to working with Zenoh](https://docs.ros.org/en/jazzy/Installation/RMW-Implementations/Non-DDS-Implementations/Working-with-Zenoh.html), the [`rmw_zenoh` repository](https://github.com/ros2/rmw_zenoh), and the [Zenoh documentation](https://zenoh.io/docs/getting-started/first-app/).

Whether Zenoh belongs inside your application, beside it, or at the center of its communication infrastructure, there is a snap-shaped way to deploy it.

[Get in touch

Interested in running Ubuntu in your organization?](https://ubuntu.com/about/contact-us/form)

## Sign up for our newsletter

Get the latest Canonical news and updates in your inbox.

Work email:

\*I agree to receive information about Canonical's
products and services.

By submitting this form, I confirm that I have read and agree to [Canonical's Privacy Policy](https://canonical.com/legal/dataprivacy).

Sign up

## Share on

---

## Related posts

[### Optimise your ROS snap – Part 6](https://canonical.com/blog/optimise-your-ros-snap-part-6)

Welcome to Part 6 of our “Optimise your ROS snap” blog series. Make sure to check Part 5. This sixth and final part will summarise every optimisation that we did. We will...

[gbeuzeboc](https://canonical.com/blog/author/gbeuzeboc)

27 April 2023

[### Optimise your ROS snap – Part 4](https://canonical.com/blog/optimise-your-ros-snap-part-4)

Welcome to Part 4 of our “optimise your ROS snap” blog series. Make sure to check Part 3 before. This fourth part is going to explain what dynamic library caching is. We will...

[gbeuzeboc](https://canonical.com/blog/author/gbeuzeboc)

21 April 2023

[### Canonical is now a platinum member in the Open Source Robotics Alliance](https://canonical.com/blog/osra-membership)

Ubuntu is the home of ROS. The very first ROS distribution, Box Turtle, launched on Ubuntu 8.04 LTS, Hardy Heron, and since then, Ubuntu and ROS have grown hand in hand. With...

[Gabriel Aguiar Noury](https://canonical.com/blog/author/g-aguiar-noury)

20 August 2025

[### ROS Noetic is EOL – take action to maintain fleet security](https://canonical.com/blog/ros-noetic-is-eol-take-action-to-maintain-fleet-security)

As of May 2025, the Robot Operating System (ROS) Noetic Ninjemys officially reached its end of life (EOL). First released in 2020 as the final ROS (1) distribution, ROS Noetic...

[Florencia Cabral Berenfus](https://canonical.com/blog/author/flor-cabral)

8 August 2025
