Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ __pycache__/
*.pyo
*.pyd
.pytest_cache/
dist/
dev/
data/
site/
secrets/
config.toml
mitm_logs
dist/
.tmp*
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ RUN pip install --no-cache-dir /app

EXPOSE 443 8883

CMD ["roborock-local-server", "serve", "--config", "/app/config.toml"]
CMD ["python", "-m", "roborock_local_server.container_entrypoint"]
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@
The best way to support this project is the next time you are buying a Roborock device come back here and use one of my affiliate links where I will receive a commission.

[![Amazon Affiliate][badge-amazon]][link-amazon]
[![Roborock 5 Off][badge-roborock-discount]][link-roborock-discount]
[![Roborock Affiliate][badge-roborock-affiliate]][link-roborock-affiliate]

[![Roborock 5 Off][badge-roborock-discount]][link-roborock-discount]

You can also support via BMAC or paypal:

Expand All @@ -21,25 +20,26 @@ This project is in VERY EARLY BETA!!! Do not use this repository unless you are

## Requirements

- Docker with `docker compose`
- `uv`
- a Linux server or Linux VM on your LAN
- a domain you control
- a place to run the stack on your LAN
- either Docker Compose or a Home Assistant installation that supports add-ons
- a second machine for onboarding later
- a Cloudflare API token with DNS edit access for the zone if you want automatic certificate renewal

## Getting Started

Start here if this is your first time setting up the stack:

1. [Installation](docs/installation.md) for requirements, network setup, configuration, and starting the stack.
2. [Cloudflare setup](docs/cloudflare_setup.md) if you want Cloudflare DNS-01 auto-renew for certificates.
3. [Onboarding](docs/onboarding.md) to pair a vacuum from a second machine after the server is running.
1. [Installation](docs/installation.md) for the shared requirements, network setup, and Docker Compose install path.
2. [Home Assistant](docs/home_assistant.md) if you want to install the stack as a Home Assistant add-on instead of Docker Compose.
3. [Cloudflare setup](docs/cloudflare_setup.md) if you want Cloudflare DNS-01 auto-renew for certificates.
4. [Onboarding](docs/onboarding.md) to pair a vacuum from a second machine after the server is running.

Additional docs:

- [Docs index](docs/index.md)
- [Tested vacuums](docs/tested_vacuums.md)
- [Home Assistant](docs/home_assistant.md)
- [Home Assistant](docs/home_assistant.md) for the add-on install path and Home Assistant integration rewiring
- [Using the Roborock App](docs/roborock_app.md)
- [Custom MQTT](docs/custom_mqtt.md)
- [Custom certificate management](docs/custom_cert_management.md)
Expand Down
4 changes: 2 additions & 2 deletions config.example.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[network]
# The one hostname the stack will serve. Keep this as the hostname only.
stack_fqdn = "roborock.example.com"
stack_fqdn = "api-roborock.example.com"
bind_host = "0.0.0.0"
# Change these if you need the stack to advertise and listen on custom ports.
# Change these if you need custom published ports.
https_port = 555
mqtt_tls_port = 8881
region = "us"
Expand Down
73 changes: 65 additions & 8 deletions docs/home_assistant.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,74 @@
# Home Assistant

Use this after [Installation](installation.md) and [Onboarding](onboarding.md) if you want Home Assistant to talk to your local stack.
This page covers two separate Home Assistant tasks:

To use this server with Home Assistant, edit your config entry at `config/.storage/core.config_entries`.
- installing the local stack as a Home Assistant add-on
- repointing Home Assistant's Roborock integration to a local stack that is already running

Find `"roborock.com"` and replace the endpoint values with your local stack URLs:
## Install As A Home Assistant Add-on

- `base_url` -> `https://api-roborock.example.com:555`
- `"a"` -> `https://api-roborock.example.com:555`
- `"l"` -> `https://api-roborock.example.com:555`
- `"m"` -> `ssl://mqtt-roborock.example.com:8881`
This is an installation method, not a post-install integration step. The add-on uses the same container image as the Docker deployment:

If you changed `network.https_port` or `network.mqtt_tls_port`, use those values instead.
- `ghcr.io/python-roborock/local_roborock_server`

### Install Steps

1. Open the Home Assistant Add-on Store.
2. Add this repository under **Repositories**:

- `https://github.com/Python-roborock/local_roborock_server`

3. Install **Roborock Local Server**.
4. Fill the add-on options:

- `stack_fqdn`
- `https_port`
- `mqtt_tls_port`
- `region`
- `admin_password`
- `protocol_login_email`
- `protocol_login_pin`
- TLS settings:
- `tls_mode = provided` with `cert_file` and `key_file`
- or `tls_mode = cloudflare_acme` with `tls_base_domain`, `tls_email`, and `cloudflare_token`

5. Start the add-on.

Then open the admin dashboard at your configured stack hostname, for example:

- `https://api-roborock.example.com:555/admin`

Do not use the Home Assistant UI hostname unless it is the same hostname covered by the TLS certificate you configured for `stack_fqdn`.

If you need the MITM protocol sync secret for the Roborock app flow, sign in to the admin page and open **Protocol Auth**. The dashboard shows the active `admin.session_secret`, so you do not need to inspect `/data/config.toml` manually.

### Add-on Behavior

- The add-on always runs the embedded MQTT broker and keeps the topic bridge enabled.
- The add-on terminates TLS itself and publishes two ports: HTTPS on `https_port` and MQTT/TLS on `mqtt_tls_port`.
- If you already manage certificates in another Home Assistant add-on such as Nginx Proxy Manager, you can point `cert_file` and `key_file` at those PEM files through `/all_addon_configs/...`.
- Installing the add-on does **not** automatically rewrite Home Assistant's Roborock integration entry.

## Repoint The Home Assistant Roborock Integration

This applies whether your local stack is running via Docker Compose or via the Home Assistant add-on.

1. Open your Home Assistant configuration directory and locate `.storage/core.config_entries`.

On many Home Assistant systems this file is at `/config/.storage/core.config_entries`.

2. Find the Roborock entry and replace the endpoint values with your local stack URLs:

- `base_url` -> `https://api-roborock.example.com:555`
- `"a"` -> `https://api-roborock.example.com:555`
- `"l"` -> `https://api-roborock.example.com:555`
- `"m"` -> `ssl://api-roborock.example.com:8881`

The current server advertises the same hostname for HTTPS and MQTT/TLS, so `"m"` should normally use the same `stack_fqdn`, not a separate `mqtt-...` hostname.

3. If you changed `https_port` or `mqtt_tls_port`, use those values instead.

4. Restart Home Assistant so the integration reloads the updated endpoints.

## Related Docs

Expand Down
9 changes: 6 additions & 3 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ Use this page as the main docs hub for setup, onboarding, and follow-up guides.

## Start Here

1. [Installation](installation.md) for requirements, network setup, configuration, and starting the stack.
2. [Cloudflare setup](cloudflare_setup.md) if you want Cloudflare DNS-01 auto-renew for certificates.
3. [Onboarding](onboarding.md) to pair a vacuum from a second machine after the server is running.
1. Read [Installation](installation.md) for the shared requirements and network setup.
2. Choose an install method:
- finish the Docker Compose steps in [Installation](installation.md)
- or use [Home Assistant](home_assistant.md) to install the stack as a Home Assistant add-on
3. Use [Cloudflare setup](cloudflare_setup.md) if you want Cloudflare DNS-01 auto-renew for certificates.
4. Run [Onboarding](onboarding.md) from a second machine after the server is running.

## Support This Project

Expand Down
101 changes: 59 additions & 42 deletions docs/installation.md
Original file line number Diff line number Diff line change
@@ -1,66 +1,77 @@
# Installation

Start here for a first-time setup. After the stack is running, continue with [Onboarding](onboarding.md) to pair a vacuum.
Start here for a first-time setup. The project supports two installation methods:

## Requirements
- Docker Compose on your own Linux host or VM
- the Home Assistant add-on from this repository

After the stack is running, continue with [Onboarding](onboarding.md) to pair a vacuum.

## Shared Requirements

- Docker with `docker compose`
- Python (I recommend installing [uv](https://docs.astral.sh/uv/getting-started/installation/))
- Two machines - one to run the server and one to do the onboarding
- A domain name that you own
- A machine that can host the stack's HTTPS and MQTT TLS ports internally on your network. The defaults are `555` and `8881`.
- A place to run the stack on your LAN
- A second machine for onboarding later
- A network that can host the stack's HTTPS and MQTT TLS ports internally. The defaults are `555` and `8881`.
- A Cloudflare API token with DNS edit access for the zone if you want Cloudflare DNS-01 auto-renew. See [Cloudflare setup](cloudflare_setup.md).

## Network Setup

1. Pick a URL for this application. It needs to be a subdomain of a domain you own, and it **must** start with `api-`. It does NOT need to be accessible outside your network - in fact, I strongly recommend you keep it internal only for now.
1. Pick a hostname for this application. It must be a subdomain of a domain you own, and it **must** start with `api-`.

For example, if you own `example.com`, I'd recommend `api-roborock.example.com`. Throughout the rest of the docs we'll refer to this as the **FQDN**. If you follow this format, you can just replace `example.com` with your real domain wherever you see it.
For example, if you own `example.com`, use `api-roborock.example.com`. Throughout the docs this is the **stack FQDN**.

2. Your network **must** handle its own DNS for the network the vacuum connects to. If it uses an external DNS server like `8.8.8.8`, this will not work.

3. Create DNS records pointing to your server's local IP address for both `api-roborock.example.com` and `mqtt-roborock.example.com`.
3. Create a DNS record pointing your stack FQDN to the local IP of the machine running the stack.

## Docker Setup
With the current server behavior, the same hostname is advertised for both HTTPS and MQTT/TLS, so you do not need a separate `mqtt-...` hostname unless you have built your own custom client routing around one.

1. Clone this repository:
## Method 1: Docker Compose

`git clone https://github.com/Python-roborock/local_roborock_server`
### Additional Requirements

2. Change into the project folder.
- Docker with `docker compose`
- Python
- [uv](https://docs.astral.sh/uv/getting-started/installation/)

```bash
cd local_roborock_server
```
### Steps

3. Install the project dependencies.
1. Clone this repository:

```bash
uv sync
```
```bash
git clone https://github.com/Python-roborock/local_roborock_server
cd local_roborock_server
```

4. Run the setup wizard.
2. Install the project dependencies:

```bash
uv run roborock-local-server configure
```
```bash
uv sync
```

3. Run the setup wizard:

```bash
uv run roborock-local-server configure
```

The wizard asks only for:
The wizard asks for:

- your `stack_fqdn` (the URL for your server - must start with `api-`)
- your HTTPS and MQTT TLS ports if you do not want the defaults `555` and `8881`
- embedded MQTT or your own broker
- whether to use Cloudflare DNS-01 auto-renew
- your admin password
- your Home Assistant/app login email and 6-digit PIN
- `stack_fqdn` (must start with `api-`)
- HTTPS and MQTT TLS ports if you do not want the defaults `555` and `8881`
- embedded MQTT or your own broker
- whether to use Cloudflare DNS-01 auto-renew
- your admin password
- your Home Assistant/app login email and 6-digit PIN

It then writes `config.toml`, generates `admin.password_hash` and `admin.session_secret`, and if you chose Cloudflare it also writes `secrets/cloudflare_token`.
It then writes `config.toml`, generates `admin.password_hash` and `admin.session_secret`, and if you chose Cloudflare it also writes `secrets/cloudflare_token`.

5. If you chose external MQTT, fill in `broker.host` in `config.toml` before starting the stack. See [Custom MQTT](custom_mqtt.md).
4. If you chose external MQTT, fill in `broker.host` in `config.toml` before starting the stack. See [Custom MQTT](custom_mqtt.md).

6. If you skipped Cloudflare, put your certificate files in `data/certs/fullchain.pem` and `data/certs/privkey.pem`. See [Custom certificate management](custom_cert_management.md).
5. If you skipped Cloudflare, put your certificate files in `data/certs/fullchain.pem` and `data/certs/privkey.pem`. See [Custom certificate management](custom_cert_management.md).

7. Start the container:
6. Start the container:

```bash
docker compose up -d --build
Expand All @@ -74,15 +85,21 @@ It then writes `config.toml`, generates `admin.password_hash` and `admin.session
docker compose up -d --build
```

8. Go to the admin dashboard: `https://api-roborock.example.com:555/admin` by default, or `https://api-roborock.example.com:YOUR_HTTPS_PORT/admin` if you chose a custom HTTPS port.
## Method 2: Home Assistant Add-on

Use [Home Assistant](home_assistant.md) as the installation guide if you want to run the stack as a Home Assistant add-on instead of Docker Compose.

## After The Stack Starts

1. Open the admin dashboard at `https://api-roborock.example.com:555/admin` by default, or `https://api-roborock.example.com:YOUR_HTTPS_PORT/admin` if you chose a custom HTTPS port.

9. Import your data from the cloud so things like routines and rooms will work. Enter your email in under cloud import, then hit send code. Once the code is returned enter the code and hit fetch data.
2. Import your data from the cloud so things like routines and rooms will work. Enter your email under cloud import, select **Send code**, then enter the returned code and select **Fetch data**.

10. For any routines that use zones, you need to re-save them so the server stores the zone data correctly. In the Roborock app, open each routine that has zones, click on the zone, tap **Edit**, click on any **Zone Cleaning** entry, then tap **Save**. Repeat for each zone in the routine.
3. For any routines that use zones, re-save them so the server stores the zone data correctly. In the Roborock app, open each routine that has zones, open the zone, tap **Edit**, open any **Zone Cleaning** entry, then tap **Save**. Repeat for each zone in the routine.

## Next Steps

- [Onboarding](onboarding.md) for pairing a new vacuum.
- [Home Assistant](home_assistant.md) if you want the local stack in Home Assistant.
- [Using the Roborock App](roborock_app.md) if you want to point the official app at your local stack.
- [Docs index](index.md) for the rest of the guides.
- [Onboarding](onboarding.md) for pairing a new vacuum
- [Home Assistant](home_assistant.md) if you want to repoint Home Assistant's Roborock integration to your local stack
- [Using the Roborock App](roborock_app.md) if you want to point the official app at your local stack
- [Docs index](index.md) for the rest of the guides
12 changes: 9 additions & 3 deletions docs/roborock_app.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

Use this after [Installation](installation.md) and [Onboarding](onboarding.md) if you want the official Roborock app to talk to your local stack.

During the MITM login step, the script now needs to sync the captured protocol-auth session back to your server. Pass `admin.session_secret` from `config.toml` as `--sync-secret`. That sync callback always uses the `--local-api` host and port.
During the MITM login step, the script now needs to sync the captured protocol-auth session back to your server. Pass `admin.session_secret` from the active server config as `--sync-secret`. That sync callback always uses the `--local-api` host and port.

The launcher can auto-load a sync secret from `config.toml` beside `mitm_redirect.py`, but that is only correct when that file matches the config used by the running server. If you run the MITM step from a second machine, or your server is using a generated Home Assistant config or another config file, pass `--sync-secret` explicitly.

The launcher now preflights that callback before starting `mitmweb`. If the `--local-api` host cannot be reached, if the TLS certificate does not validate for that host, or if the sync secret is rejected, the script exits immediately instead of letting you proceed into a broken login flow.

Expand All @@ -16,7 +18,9 @@ The launcher now preflights that callback before starting `mitmweb`. If the `--l
uv run mitm_redirect.py --local-api api-roborock.example.com --sync-secret YOUR_ADMIN_SESSION_SECRET
```

Use the `admin.session_secret` value from `config.toml` for `YOUR_ADMIN_SESSION_SECRET`.
Use the `admin.session_secret` value from the config file your running server actually uses for `YOUR_ADMIN_SESSION_SECRET`.

If startup fails with `invalid_sync_secret`, the launcher either auto-loaded the wrong local `config.toml` or you copied a stale secret. Re-read `admin.session_secret` from the active server config and pass it explicitly with `--sync-secret`.

If you use the default local stack ports, host-only values are fine here: the script assumes HTTPS `:555` and MQTT TLS `:8881`.

Expand Down Expand Up @@ -119,7 +123,9 @@ Make sure you have the following installed:
uv run mitm_redirect.py --local-api api-roborock.example.com --sync-secret YOUR_ADMIN_SESSION_SECRET
```

Use the `admin.session_secret` value from `config.toml` for `YOUR_ADMIN_SESSION_SECRET`.
Use the `admin.session_secret` value from the config file your running server actually uses for `YOUR_ADMIN_SESSION_SECRET`.

If startup fails with `invalid_sync_secret`, the launcher either auto-loaded the wrong local `config.toml` or you copied a stale secret. Re-read `admin.session_secret` from the active server config and pass it explicitly with `--sync-secret`.

If you use the default local stack ports, host-only values are fine here: the script assumes HTTPS `:555` and MQTT TLS `:8881`.

Expand Down
2 changes: 1 addition & 1 deletion mitm_redirect.py
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,7 @@ def _rewrite_value(text: str) -> str:
parser.add_argument(
"--sync-secret",
default=None,
help="Optional admin.session_secret for protocol auth sync. Defaults to config.toml when available.",
help="Optional admin.session_secret for protocol auth sync. Defaults to ./config.toml beside this script when available; pass explicitly when the server uses a different active config.",
)
parser.add_argument("--mode", default="wireguard", help="mitmweb proxy mode (default: wireguard)")
parser.add_argument("--listen-port", default=None, help="mitmweb listen port")
Expand Down
2 changes: 1 addition & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ nav:
- Support This Project: support.md
- Getting Started:
- Installation: installation.md
- Home Assistant: home_assistant.md
- Cloudflare Setup: cloudflare_setup.md
- Onboarding: onboarding.md
- Integrations:
- Home Assistant: home_assistant.md
- Using the Roborock App: roborock_app.md
- Reference:
- Tested Vacuums: tested_vacuums.md
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "roborock-local-server"
version = "0.0.2-rc1"
version = "0.0.2-rc6"
description = "private local Roborock server stack."
requires-python = ">=3.11,<3.14"
readme = "README.md"
Expand Down
3 changes: 3 additions & 0 deletions repository.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
name: Roborock Local Server Apps
url: "https://github.com/Python-roborock/local_roborock_server"
maintainer: Luke Lashley
5 changes: 5 additions & 0 deletions roborock_local_server_addon/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Changelog

## 0.0.2-rc6

- Initial Home Assistant add-on manifest using the shared GHCR image.
Loading