Roomba Cloud is a local replacement for the cloud services used by iRobot V4 robots. It lets a compatible robot connect to your own server, keeping its telemetry and maps on your network and making them available to Roomba Local for Home Assistant. No custom robot firmware is required; we provision the robot over Bluetooth.
This is an independent project, not affiliated with iRobot.
| Model | Tested firmware | Status |
|---|---|---|
| Roomba 505/507 | p25-505+9.3.6+I3.8.149 |
Physically tested |
Other V4 models have not been verified.
- A domain name you control, with a publicly trusted TLS certificate for it. The emulator includes ACME/Let's Encrypt support
- A server running Docker with TCP ports 443 (HTTPS) and 8883 (MQTT) reachable from the robot and 443 reachable from Home Assitant
- A Bluetooth-capable computer near the robot for provisioning, with Python and Bluetooth access. This can be a different computer from the server.
⚠️ The roomba requires an NTP server to continue functioning. You can either allow NTP traffic from it to the internet, or setup your own NTP server and point*.irobot.pool.ntp.orgto it.
Keep the emulator on a trusted, firewalled LAN. Do not expose it to the Internet.
Configure DNS so that roomba.example.com (your domain) resolves to your Docker server's LAN
address from the robot's network. Keep the default published ports, 443 and
8883, available. This A record can be local, it doesn't need to be on public DNS.
- Docker Compose: use the supplied configuration to create both containers and their storage.
- Manual container setup: configure the containers through TrueNAS, Unraid, Portainer, or another container manager.
- Native Python installation: run directly on a Linux host without Docker.
Download the Compose file and environment template from the latest stable release:
mkdir roomba-cloud
cd roomba-cloud
curl -fL https://github.com/carbon198/roomba-cloud/releases/latest/download/compose.yaml -o compose.yaml
curl -fL https://github.com/carbon198/roomba-cloud/releases/latest/download/default.env.example -o .env.example
cp .env.example .env
mkdir -p certsEdit .env and set:
HOSTNAME=roomba.example.comLeave the port and storage settings at their defaults.
Option A: Built-in Let's Encrypt DNS validation
In .env, leave TLS_CERT and TLS_KEY empty and set:
TLS_CERT=
TLS_KEY=
ACME_EMAIL=you@example.com
ACME_AGREE_TOS=true
ACME_STAGING=falseUse your own email address. Set ACME_AGREE_TOS=true only after accepting the
Let's Encrypt subscriber agreement.
You will need to add a TXT to your DNS provider record after starting the containers below.
Option B: Supply an existing certificate
Click to Expand
Copy the full certificate chain and matching unencrypted private key into
certs/fullchain.pem and certs/privkey.pem.
Set these values in .env:
TLS_CERT=/certs/fullchain.pem
TLS_KEY=/certs/privkey.pemThe containers run as UID/GID 10001, so give that user access:
sudo chown 10001:10001 certs certs/fullchain.pem certs/privkey.pem
sudo chmod 700 certs
sudo chmod 600 certs/fullchain.pem certs/privkey.pemUser-supplied certificate and ACME are mutually exclusive.
docker compose pull
docker compose up -d
docker compose logs -f httpsIf using built-in Let's Encrypt, wait for an acme_dns_challenge event:
{"event":"acme_dns_challenge","name":"_acme-challenge.roomba.example.com","type":"TXT","value":"<challenge value>"}Add the exact TXT value at the public DNS name shown in the log. Leave the containers running: the server waits for DNS propagation, then requests the certificate automatically. It allows up to 30 minutes for propagation. If the attempt times out, follow the logs for the next attempt and its current value.
Click to Expand
The HA addon includes a sensor with the TXT challenge value. If you can update your DNS provider within HA, using an automation is probably the easiest route. The sensor value will be Unknown when no TXT update is needed.
The HTTPS service also writes /data/dns-challenges/challenge.json:
{"name":"_acme-challenge.roomba.example.com","type":"TXT","value":"<challenge value>"}The separate Compose dns-challenges volume contains only these public challenge
details.
Have your DNS updater read /challenges/challenge.json, add the TXT value
through your DNS provider. When the cert is renewed, challenge.json will be deleted.
The customer token is your login credential and is generated automatically on first startup
docker compose exec https cat /data/customer-token.txtPaste the key into the web login page at https://<your-hostname>. Save it somewhere; the same key is also
used by Home Assistant to authenticate.
Click to Expand
| Setting | Value |
|---|---|
| Image repository | ghcr.io/carbon198/roomba-cloud |
| Image tag | Your chosen release tag, or latest |
| Published TCP ports (host → container) | 443 → 8443 and 8883 → 8883 |
With host networking, omit port mappings and set HTTPS_PORT=443 and
MQTT_PORT=8883.
Set HOSTNAME=roomba.example.com to your DNS hostname.
Configure DNS as described in the Compose instructions.
HTTPS is advertised on the standard public port 443.
For built-in Let's Encrypt, set these additional variables:
| Variable | Value |
|---|---|
ACME_EMAIL |
Your email address |
ACME_AGREE_TOS |
true, after accepting the Let's Encrypt terms |
Leave TLS_CERT and TLS_KEY unset in this mode. Alternatively, mount supplied
certificates as described below and set TLS_CERT=/certs/fullchain.pem and
TLS_KEY=/certs/privkey.pem, leaving ACME options unset.
Other settings can remain at their defaults.
| Storage | Mount inside container | Access |
|---|---|---|
| Roomba Data/Maps | /data |
Read/write |
| DNS challenge directory (optional for sharing with an updater) | /data/dns-challenges |
Read/write |
| Supplied certificate directory (not needed for built-in ACME) | /certs |
Read-only |
The private /data directory must be owned by UID/GID 10001 with mode
0700. Keep it on local storage supporting Unix sockets.
Start the container. For built-in ACME, watch its logs and complete the TXT challenge as described above, or have your DNS updater read the shared challenge directory. MQTT waits until the certificate is available.
Open your configured HTTPS address. In your container manager's console run:
cat /data/customer-token.txtUse that customer key to sign in, then continue to Bluetooth provisioning.
Click to Expand
Download the source first:
git clone https://github.com/carbon198/roomba-cloud.git
cd roomba-cloudFrom that repository directory:
python3.14 -m venv .venv
.venv/bin/python -m pip install -r requirements.txt
mkdir -p tools
cc -O2 -Wall -Wextra -Werror native/mqtt_tls_bridge.c -o tools/mqtt_tls_bridge -lssl -lcryptoRun these in two terminals, both in the repository directory. These
examples use sudo to bind HTTPS port 443; both processes must run as the
same user and share the same data directory.
# Terminal 1
sudo .venv/bin/python -m roomba_cloud mqtt \
--hostname roomba.example.com --https-port 443 --data-dir ./data \
--acme-email you@example.com --acme-agree-tos# Terminal 2
sudo .venv/bin/python -m roomba_cloud https \
--hostname roomba.example.com --https-port 443 --data-dir ./data \
--acme-email you@example.com --acme-agree-tosRetrieve the key with sudo cat ./data/customer-token.txt. These commands run
in the foreground; arrange service supervision yourself if needed.
Start the emulator and verify its HTTPS page works before provisioning. Provisioning changes the robot's Wi-Fi and cloud settings and will disconnect the robot from the cloud. It won't break Matter integrations though. There is no need to factory reset the robot. The emulator will pull your existing maps from the robot.
Provisioning does not have to run on the emulator server. Clone or download this repository on any Bluetooth-capable computer, move near the robot, and run the tool there.
Download the source on the Bluetooth computer, if you do not already have it:
git clone https://github.com/carbon198/roomba-cloud.git
cd roomba-cloudFrom that repository directory:
Linux / macOS
python3 -m venv .venv
.venv/bin/python -m pip install -r requirements-provisioning.txt
.venv/bin/python -m provisioning.ble_provision --ssid 'YOUR_WIFI_SSID' \
--domain roomba.example.com --country US --timezone America/New_YorkWindows (PowerShell)
py -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements-provisioning.txt
.\.venv\Scripts\python.exe -m provisioning.ble_provision --ssid "YOUR_WIFI_SSID" --domain roomba.example.com --country US --timezone America/New_YorkReplace the Wi-Fi name, country, and timezone with your own values.
- Keep the robot nearby and ready for Wi-Fi/Bluetooth setup. Select a Bluetooth adapter if prompted, then select your robot from the scan results.
- Enter the Wi-Fi password at the hidden prompt.
- Follow the authorization prompt. If requested, press the robot's Power button once after it beeps. An already authorized robot may proceed without another button press.
- Wait while settings are written and the robot joins Wi-Fi. The tool displays a generated robot password once; retain it privately if needed. This is not the customer key used to sign in.
- Open the dashboard link, sign in with your customer key, and confirm the robot appears with an online MQTT connection.
If you encounter issues, add --debug to the provisioning command for additional diagnostics
Open your configured HTTPS address and enter the customer key. The browser remembers it across refreshes and restarts until you Sign out or clear the site's stored data. Use this only on a trusted device.
The dashboard provides:
- Robot status: robot ID, reported model/SKU, IP address, MQTT connection, battery, mission phase, firmware, and last-seen time. It refreshes automatically.
- Maps and rooms: open a robot's room editor and select a saved map to view it.
- Map editing: rename rooms, split a room, merge adjacent rooms, or delete an available map. These actions change the robot's saved map, not just the displayed image. Map changes cannot be reverted.
Editing and deletion require the robot to be idle with no mission. Controls are locked during running or paused missions, or when mission state is unknown. After an edit, wait for the robot's updated map before making another change. Maps and room details appear as the robot reports them; missing data is not necessarily a setup failure.
For cleaning controls and day-to-day automation, install Roomba Local for Home Assistant and follow its setup instructions. Use the emulator's HTTPS address, customer key, and the robot ID shown on the dashboard.
If you want to reconnect your Roomba to the manufacturer's cloud, simply follow the Change Wi-Fi process in the Roomba Home app. Click your robot -> Robot Settings -> Change Wi-Fi.
Q: Why can't we do all this in a Home Assistant App? A: I would like to, but I haven't been able to coerce the Roomba to connect on non-standard HTTPS and MQTT ports. Most people already use 443 and 8883 on Home Assistant and the Roomba does some weird MQTT stuff that Mosquitto doesn't handle.
Q: Will this wipe my Roomba? A: No, the provisioning is the same as the Roomba Home app's Change Wi-Fi feature. It does not wipe the robot
Q: Can I use my existing maps? A: Yes please do, the emulator will pull them from the robot automatically
Q: Should I block the Roomba's internet? A: I do, and you probably should. I can't guarantee they won't block this provisioning process in the future. Be sure to provide NTP server access to it as detailed in the Requirements section above.
Q: Can this brick the Roomba? A: No not to my knowledge, we aren't flashing the firmware. Using the map editor always entails some risk you might lose or corrupt your maps, but that's the extent of the risk.
Q: Do I need to backup the /data folder? A: Not really. All the historical state will be in Home Assistant. If you need to setup this project on a new server you can reprovision the robot, repoint Home Assistant and everything will continue working as normal.
Q: Can the emulator restore maps to a robot? A: I've been researching that but I haven't figured out how to get the robot to download them as yet.
Q: Do V4 Roombas not have a local MQTT server? A: They do, but it isn't for local robot control. It only turns on when sending it certain bluetooth commands and it appears to be for firmware provisioning. One promising thing about that is it looks like you can upload new firmware signing keys, so custom firmware for these robots may be possible in the future.