This image runs the OLO Appliance.
This guide focuses only on how to run the image and which options you can configure.
olorobotics/olo-appliance:humble-latestolorobotics/olo-appliance:jazzy-latestdocker pull olorobotics/olo-appliance:humble-latest
docker run -d \
--net=host \
--name olo-appliance \
-e OLO_APL_DEVICE_API_KEY="apl_your-device-api-key" \
-e OLO_APL_APPLIANCE_NAME="My Appliance" \
-v olo-data:/data \
olorobotics/olo-appliance:humble-latest
This starts the appliance with persistent storage using the olo-data Docker volume. The appliance resolves its robot identity from the server automatically on first boot.
services:
olo-appliance:
image: olorobotics/olo-appliance:humble-latest
container_name: olo-appliance
network_mode: host
environment:
OLO_APL_DEVICE_API_KEY: "apl_your-device-api-key"
OLO_APL_APPLIANCE_NAME: "My Appliance"
volumes:
- olo-data:/data
restart: unless-stopped
volumes:
olo-data:
driver: local
The recommended way to authenticate is with a device API key provisioned from the OLO portal:
OLO_APL_DEVICE_API_KEY - Device API key (prefix apl_). If omitted, the appliance falls back to the interactive device authorization flow on startup.OLO_APL_APPLIANCE_NAME - A name for this appliance instance (e.g., My Appliance)Optional:
OLO_APL_ROBOT_ID - Robot ID. Auto-resolved from the server on first boot if not provided. Setting it explicitly skips the initial server round-trip.You can obtain the device API key from the OLO portal when registering a new appliance.
If no OLO_APL_DEVICE_API_KEY is set, the appliance automatically starts an OAuth 2.0 device authorization flow (RFC 8628). This is useful for first-time setup or environments where pre-provisioning an API key is not practical.
How it works:
/data/.appliance.json so subsequent restarts authenticate automatically.To see the prompt, check the container logs:
docker logs olo-appliance
The device flow times out after 30 minutes. If it expires, restart the container to try again.
Starting without an API key (device flow):
docker run -d \
--net=host \
--name olo-appliance \
-e OLO_APL_APPLIANCE_NAME="My Appliance" \
-v olo-data:/data \
olorobotics/olo-appliance:humble-latest
# Watch the logs for the authorization prompt
docker logs -f olo-appliance
OLO_APL_FORCE_DEVICE_FLOW - Set to true to force the device authorization flow even when a persisted API key exists. Useful for re-provisioning an appliance to a different account or organization.OLO_APL_MANAGEMENT_SECRET - Shared secret for securing management API endpoints (/device-flow/start, /device-flow/status, /device-flow/cancel). When set, requests to these endpoints must include the secret as a Bearer token in the Authorization header. Only needed for advanced or programmatic use.By default, the appliance launches its own rosbridge server on localhost:9090. You can configure it to use an external rosbridge server:
OLO_APL_ROSBRIDGE_HOST - Rosbridge server hostname (default: localhost)OLO_APL_ROSBRIDGE_PORT - Rosbridge server port (default: 9090)OLO_APL_DISABLE_LOCAL_ROSBRIDGE - Set to true to disable the built-in rosbridge serverNote: You can also configure rosbridge settings through the Maintenance window in the OLO UI. However, be careful when changing the rosbridge host/port via the UI - the setting must be valid from the container's perspective. For example, if you're using host networking, localhost refers to the host machine. If you're using bridge networking with port mappings, you may need to use the container's internal network address or host.docker.internal (on Docker Desktop) to reach services on the host.
Example connecting to an external rosbridge:
docker run -d \
--net=host \
--name olo-appliance \
-e OLO_APL_DEVICE_API_KEY="apl_your-device-api-key" \
-e OLO_APL_APPLIANCE_NAME="My Appliance" \
-e OLO_APL_ROSBRIDGE_HOST="192.168.1.100" \
-e OLO_APL_ROSBRIDGE_PORT="9090" \
-e OLO_APL_DISABLE_LOCAL_ROSBRIDGE="true" \
-v olo-data:/data \
olorobotics/olo-appliance:humble-latest
OLO_APL_USE_SIM_TIME - Set to true to use simulation time (default: false)ROS_DOMAIN_ID - ROS 2 domain ID for DDS communication (default: 0)Control topic publishing rates to manage bandwidth:
OLO_APL_TOPIC_DEFAULT_THROTTLE_HZ - Default throttle frequency in Hz for all topics (leave unset or 0 to disable)OLO_APL_TOPIC_HANDLING_JSON - Complete topic handling configuration as JSONExample topic handling configuration:
docker run -d \
--net=host \
--name olo-appliance \
-e OLO_APL_DEVICE_API_KEY="apl_your-device-api-key" \
-e OLO_APL_APPLIANCE_NAME="My Appliance" \
-e OLO_APL_TOPIC_HANDLING_JSON='{"defaultThrottleFrequency": 20, "throttleTopics": {"/odom": 10, "/camera/image_raw": 5}, "throttleDataTypes": {"sensor_msgs/msg/PointCloud2": 2}}' \
-v olo-data:/data \
olorobotics/olo-appliance:humble-latest
Topic Handling Options:
defaultThrottleFrequency - Default throttle rate in Hz for all topicsthrottleTopics - Per-topic throttle rates (highest priority)throttleDataTypes - Per-message-type throttle rates (second priority)Configuration priority: throttleTopics > throttleDataTypes > defaultThrottleFrequency
The appliance can source an external ROS2 workspace, making it aware of custom message types, services, and packages from your robot. This is essential when your robot uses custom interfaces that the appliance needs to understand.
Set the ROS2_WS_PATH environment variable to point to a ROS2 workspace inside the container. When the appliance starts, it will source $ROS2_WS_PATH/install/setup.bash after sourcing the base ROS distribution.
The recommended approach is to use a shared Docker volume that contains your built ROS2 workspace. A robot driver container can export its workspace, and the appliance can import it read-only:
services:
olo-appliance:
image: olorobotics/olo-appliance:humble-latest
network_mode: host
environment:
OLO_APL_DEVICE_API_KEY: "apl_your-device-api-key"
OLO_APL_APPLIANCE_NAME: "My Appliance"
ROS2_WS_PATH: /shared/workspace
volumes:
- olo-data:/data
- ros-workspace:/shared/workspace:ro # Read-only access to shared workspace
my-robot-driver:
image: my-robot-driver:humble-latest
network_mode: host
environment:
EXPORT_WORKSPACE: "1" # Driver exports its workspace on startup
volumes:
- ros-workspace:/shared/workspace:rw # Read-write to populate the workspace
volumes:
olo-data:
driver: local
ros-workspace:
driver: local
Key Points:
rw) and exports its built workspacero) and sources it via ROS2_WS_PATHA common deployment pattern is running the OLO Appliance alongside one or more containerized robot drivers. All containers share the host network for ROS 2 DDS discovery to work correctly.
This example shows the appliance running alongside a robot driver, with a shared ROS workspace volume:
services:
olo-appliance:
image: olorobotics/olo-appliance:humble-latest
init: true
restart: unless-stopped
stop_signal: SIGINT
stop_grace_period: 40s
network_mode: host
environment:
OLO_APL_DEVICE_API_KEY: "apl_your-device-api-key"
OLO_APL_APPLIANCE_NAME: "My Appliance"
ROS_DOMAIN_ID: 55
ROS_AUTOMATIC_DISCOVERY_RANGE: SUBNET
FASTDDS_BUILTIN_TRANSPORTS: UDPv4
ROS_LOCALHOST_ONLY: 0
ROS2_WS_PATH: /shared/workspace
volumes:
- olo-appliance-data:/data
- ros-workspace:/shared/workspace:ro
my-robot-driver:
image: your-robot-driver:humble-latest
init: true
restart: unless-stopped
stop_signal: SIGINT
stop_grace_period: 40s
network_mode: host
environment:
ROS_DOMAIN_ID: 55
ROS_AUTOMATIC_DISCOVERY_RANGE: SUBNET
FASTDDS_BUILTIN_TRANSPORTS: UDPv4
ROS_LOCALHOST_ONLY: 0
volumes:
- ros-workspace:/shared/workspace:rw
# If your driver needs hardware access:
# devices:
# - "/dev/ttyUSB0:/dev/ttyUSB0"
volumes:
ros-workspace:
driver: local
olo-appliance-data:
driver: local
network_mode: host - Required for ROS 2 DDS discovery between containers and with nodes on the host/LANROS_DOMAIN_ID - Must match across all containers and external ROS nodesROS_AUTOMATIC_DISCOVERY_RANGE: SUBNET - Allows discovery across the local subnetFASTDDS_BUILTIN_TRANSPORTS: UDPv4 - Forces UDP transport (see Troubleshooting)ros-workspace volume - Shared workspace for custom message typesinit: true - Proper signal handling for graceful shutdown# Start all services
docker compose up -d
# Start just the appliance
docker compose up -d olo-appliance
# View logs
docker compose logs -f
Recommended: host networking
For most setups, run the appliance with host networking (--net=host or network_mode: host). This is required for ROS 2 DDS discovery to work when your robot is on another computer on the same network, as the container needs to receive multicast packets for node discovery.
In this mode you do not use -p port mappings; the container shares the host's network stack directly.
Optional: Diagnostics / Health API (bridge networking only)
If you choose to run without host networking (Docker bridge mode), the appliance exposes an internal HTTP endpoint on port 8443 inside the container.
To access this from outside the container (for basic health checks) in bridge mode, you can publish the port:
docker run -d \
--name olo-appliance \
-e OLO_APL_DEVICE_API_KEY="apl_your-device-api-key" \
-e OLO_APL_APPLIANCE_NAME="My Appliance" \
-v olo-data:/data \
-p 9443:8443 \
olorobotics/olo-appliance:humble-latest
Then, for example:
curl http://localhost:9443/health
Publishing this port is optional and not required for normal operation.
ROS 2 / DDS networking (important)
Docker's default bridge network blocks multicast traffic, which ROS 2 DDS relies on for node discovery. If your robot is running on another computer on the same network, the appliance will not be able to discover it without host networking.
When using host networking, you do not use -p port mappings (the container shares the host's ports directly).
The appliance stores all persistent data under /data inside the container. This unified directory contains:
/data/recordings/rosbags - ROS bag recordings/data/script-logs - Script execution logs/data/cached-scripts - Cached scripts/data/scheduled-scripts - Scheduled script data/data/cache/olo-client - OLO client cacheRecommended: Use a named volume for persistence across restarts:
docker volume create olo-data
docker run -d \
--net=host \
--name olo-appliance \
-e OLO_APL_DEVICE_API_KEY="apl_your-device-api-key" \
-e OLO_APL_APPLIANCE_NAME="My Appliance" \
-v olo-data:/data \
olorobotics/olo-appliance:humble-latest
Or with Docker Compose:
services:
olo-appliance:
image: olorobotics/olo-appliance:humble-latest
network_mode: host
environment:
OLO_APL_DEVICE_API_KEY: "apl_your-device-api-key"
OLO_APL_APPLIANCE_NAME: "My Appliance"
volumes:
- olo-data:/data
volumes:
olo-data:
driver: local
If you're having issues with ROS 2 nodes not discovering each other (topics not visible, services not found), try forcing the DDS transport to UDPv4:
environment:
FASTDDS_BUILTIN_TRANSPORTS: UDPv4
Or via command line:
docker run -d \
--net=host \
--name olo-appliance \
-e OLO_APL_DEVICE_API_KEY="apl_your-device-api-key" \
-e OLO_APL_APPLIANCE_NAME="My Appliance" \
-e FASTDDS_BUILTIN_TRANSPORTS="UDPv4" \
-v olo-data:/data \
olorobotics/olo-appliance:humble-latest
This is particularly helpful when:
For more control over ROS 2 discovery:
environment:
ROS_DOMAIN_ID: 55 # Match across all nodes
ROS_AUTOMATIC_DISCOVERY_RANGE: SUBNET # Discover nodes on local subnet
ROS_LOCALHOST_ONLY: 0 # Allow non-localhost communication
FASTDDS_BUILTIN_TRANSPORTS: UDPv4 # Force UDP transport
OLO_APL_DEVICE_API_KEY is set correctly (must start with apl_)docker logs olo-appliance for the device authorization flow prompt with a verification URL and user codeOLO_APL_FORCE_DEVICE_FLOW=truedocker logs olo-appliance-p 9443:8443Content type
Image
Digest
sha256:0d469993d…
Size
2.3 GB
Last updated
3 days ago
docker pull olorobotics/olo-appliance:jazzy-latest