The handful of environment variables below control most of ROS 2’s network behavior. Most days you set them once in ~/.bashrc and forget about them; on the days they matter, they matter a lot.
The four that come up most
| Variable | Default | When to change |
|---|---|---|
ROS_DOMAIN_ID |
0 |
Running multiple parallel stacks on one host — see DDS domain isolation. |
ROS_LOCALHOST_ONLY |
unset | Set to 1 to restrict DDS to loopback (no LAN discovery) — faster startup, no inter-machine visibility. |
RMW_IMPLEMENTATION |
rmw_fastrtps_cpp |
Set to rmw_cyclonedds_cpp for latency-critical tuning — see ROS 2 latency tuning. |
CYCLONEDDS_URI |
unset | CycloneDDS-specific XML config; restrict interfaces, tune discovery. |
Recommended ~/.bashrc setup (single host)
source /opt/ros/jazzy/setup.bash
export ROS_DOMAIN_ID=0
export ROS_LOCALHOST_ONLY=1
# Leave RMW_IMPLEMENTATION default unless latency profiling says otherwise
ROS_LOCALHOST_ONLY=1 is the highest-leverage setting most users miss — it removes the cost of DDS announcing itself on every NIC on the machine, which speeds up node startup and avoids accidentally discovering nodes on a laptop’s docker network.
Recommended .env_researchbest setup (parallel stack)
SITL_INSTANCE=1
MAVLINK_PORT=5770
GZ_PARTITION=researchbest
ROS_DOMAIN_ID=42
ROS_LOCALHOST_ONLY=1
GZ_HEADLESS=1
This is the configuration used by the parallel researchbest stack — see Parallel SITL instances for the full story.
What printenv | grep -i ros should show
ROS_DISTRO=jazzy
ROS_DOMAIN_ID=0
ROS_LOCALHOST_ONLY=1
AMENT_PREFIX_PATH=/opt/ros/jazzy
...
If ROS_DISTRO isn’t set, you forgot to source /opt/ros/jazzy/setup.bash. If ROS_DOMAIN_ID is missing, you’re on the default 0 (usually fine for a single host).
Where to go next
- DDS domain isolation — the deeper context for
ROS_DOMAIN_ID - QoS profiles — the per-topic configuration layer
- ROS 2 latency tuning — when to deviate from defaults