# teddycloud: a local server for your Toniebox

> teddycloud is a C implementation of an alternative cloud server for the Toniebox, so the figurine audio and the box itself talk to a server you control instead of the manufacturer's. It ships as a Docker image with the web frontend built in, and the two-repository split between the backend and the frontend is the part of the contribution workflow you need to understand before you open a pull request.

**toniebox-reverse-engineering/teddycloud** — teddyCloud is an open source server replacement for the Boxine Cloud

- Repository: https://github.com/toniebox-reverse-engineering/teddycloud
- Website: https://toniebox-reverse-engineering.github.io/docs/tools/teddycloud/
- Stars: 1,081 · Forks: 91
- Language: C
- License: GPL-2.0
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/toniebox-reverse-engineering-teddycloud

## The point is control over the vendor's cloud

TeddyCloud is an alternative server for your Toniebox, allowing you to host the cloud services locally. The README states the motivation in two sentences, and they are the whole case for the project: this gives you the control about which data is sent to the original manufacturer's cloud, and it allows you to host your own figurine audio files on, for example, your NAS or any other server.

A Toniebox is a speaker for audio figurines, and the audio is fetched from a cloud service run by the manufacturer. The privacy objection is that the device is talking to somebody else's server indefinitely, and the practical objection is that the audio lives somewhere you do not control.

The project is a reimplementation of that server's API rather than a wrapper around it, written in C, and it is licensed under GPL-2.0. The primary language in the repository listing is C, which is a deliberate choice for a service that runs on small hardware, and the build tree is a mix of C sources with vendored dependencies, cJSON, ogg, opus, fat and proto directories.

The project lives under the toniebox-reverse-engineering organisation, and the documentation is a website at toniebox-reverse-engineering.github.io, with a per-tool page for teddycloud itself.

## What is actually implemented

The feature list is long and specific, and it is the best available description of how much of the original service has been reimplemented.

On the content side, it provides audio content over the air, caches the original tonie audio content, simulates live content with the .live extension, and passes through the original tonie audio content. It converts any audio file to a tonie audio file through the web interface, and it converts audio streams on the fly via ffmpeg for webradio and for streams.

On the device side there is more. It can filter custom tags to prevent deletion with the .nocloud mechanism, configure the maximum volume for the speaker and for headphones, configure the LED, configure the slapping behaviour, and customise the original box sounds such as the jingle, over the air.

Then the things that are not about audio at all. It can extract and inject certificates on an esp32 firmware dump, it can decode RTNL logs, and it has an MQTT client with a Home Assistant integration over MQTT, alongside a separate web frontend repository.

Two features in that list are worth a note. The certificate extraction and injection is the part that lets you point the box at your own server, because the box has to trust it, and the .nocloud tag filtering is what stops the box from deleting the figurines it can no longer find upstream. Both are the kind of detail that shows this is a working reimplementation rather than a prototype.

## What is planned, and which branch to build from

The Planned section is short: teddyBench integration and Toniebox 2 support.

That is worth reading as a statement of where the project is. Work on a teddyBench integration is listed there as planned rather than implemented. Toniebox 2 support means a newer generation of the hardware, and the fact that it is listed as planned rather than implemented tells you the current target is the first generation.

The development guidance is more concrete. Use the develop branch for development and pull requests, and note that stable builds are available from the master branch. And do not forget to clone the submodules with --recurse-submodules.

That last instruction is the one that trips up a first-time contributor, because the submodules are not optional here. The web frontend is a submodule, and the vendored dependencies are submodules, and a clone without them produces a tree that builds but has nothing in it.

The starting point for a user is the guide on the project website, and the README points there for anyone who wants to get going.

## Two repositories and a rule about submodule pointers

The contribution workflow is the part of this project that is genuinely unusual, and it is worth reading twice if you plan to contribute.

TeddyCloud consists of two repositories: the backend, which is this one, and the web frontend, teddycloud_web, which is included as a submodule. The built web files live in contrib/data/www/.

The workflow for contributors has three cases. For backend-only changes, you open a pull request against teddycloud and no submodule changes are needed. For frontend-only changes, you open a pull request against teddycloud_web and no pull request against teddycloud is needed. And for changes in both, you create and merge both pull requests separately, with teddycloud_web first and then teddycloud, and the instruction is explicit: do not commit submodule pointer changes in the teddycloud pull request, because a maintainer will handle that.

The two GitHub Actions workflows complete the picture. The Make web and commit workflow is triggered manually with workflow_dispatch, and it builds the web from the teddycloud_web submodule, commits the files to contrib/data/www/, pushes, and triggers the Docker build. The Docker Image Publish Matrix workflow runs on a push to master or develop, or on tags, and builds the Docker images automatically.

After merging, a maintainer runs the make web and commit workflow, which builds the frontend from the current submodule state on the same branch, commits the built files and updates the submodule pointer if needed, and the resulting push triggers the Docker build.

The reason for the rule is not hard to guess. The submodule pointer is a conflict magnet in a project where the frontend changes on its own schedule, and keeping it out of contributor pull requests means the merge of the two projects never depends on who won a race.

## The container image and the sanitizers

The Dockerfile is a two-stage build on Ubuntu, and it has a few details that say something about how the project is developed.

The build stage installs gcc, the protobuf-c-compiler, build-essential, git, zip, curl and ca-certificates, then fetches two JSON files, tonies.json and tonieboxes.json, from the tonies-json repository, with the fetch guarded so a failure does not stop the build. The compile step is make test_git_version && make zip, and the sanitizers are on by default, with an ARG NO_SANITIZERS=0 to turn them off, which the comment in the file calls the default.

That is unusual for a released container, and it is a deliberate choice: this is a project where the maintainers want the sanitizers active in the images people run, because the code parses data from a network protocol and from firmware dumps.

The runtime stage installs libubsan1 for the undefined behaviour sanitizer, strace, ffmpeg, curl, ca-certificates, gosu and libcap2-bin, and it creates the directory tree the server expects: certs, config, data/content/default, data/library, data/firmware, data/www with a custom_img and plugins subdirectory, and data/cache. The image exposes ports 80, 443 and 8443, and there is a comment about allowing a non-root user to bind privileged ports.

DockerfileAlpine, DockerfileDebian and DockerfileUbuntu sit alongside the main Dockerfile, so the same build can be produced on more than one base image.

## The Makefile and the build matrix

The Makefile is where the build's shape is visible.

The directory layout is conventional for a C project with generated content, with BIN_DIR for the executable, OBJ_DIR for objects, SRC_DIR for the sources, CONTRIB_DIR for the bundled resources, INSTALL_DIR for the install tree, PREINSTALL_DIR for the pre-install payload, and separate directories for the web sources, the web build output and the final web data directory. The executable itself is built as bin/teddycloud, with a link object alongside it.

The platform detection is the interesting part. On Windows the shell environment is cmd, the architecture is fixed to AMD64 and the OS identifier is windows, while on everything else the shell is bash, the architecture comes from uname -m and the OS identifier is parsed out of /etc/os-release. The bitness is then read from getconf LONG_BIT, giving a 64 or 32 value.

There is also a Windows-specific file, vcvars.bat, and a make.exe at the repository root, which is a hint that the build has been made to work from a Windows command prompt as well as from bash.

The version stamping is thorough, with variables for the dirty flag, the build time, the short SHA, the full SHA and the tag, each falling back to a placeholder when git is not available. The build timestamp is produced differently on the two shells, with date /t and time /t on Windows and a formatted date elsewhere, and RUNTIME_BASE_PATH and CONFIG_RUNTIME_BASE_PATH become compile time defines so the paths are baked into the binary.

The test variables are worth noting too, with fixed ports for the HTTP and HTTPS API tests, which means the test suite expects to bind specific ports on a developer machine.

## Development tools: a sandbox, a devcontainer and a debugger

The project takes developer experience seriously enough to ship three separate tools for it.

The dev-sandbox/ directory runs TeddyCloud locally with mock data, with tonies, a Toniebox and TAF, so you can try out features and see changes during development without any hardware. It builds and runs a local image, and its own README has the details.

The editor path is documented step by step. You build once with Terminal, or F1, and Run Task, and build, which uses the tasks in .vscode/tasks.json. Then you open Run and Debug, select the linux teddyCloud configuration and press F5, which uses .vscode/launch.json. The F5 run executes the prelaunch build task automatically and starts bin/teddycloud under gdb.

For the web interface in a devcontainer, you open http://localhost:port/web on the forwarded HTTP port, and the port is found in the Ports view. There is also a .devcontainer/ directory in the repository, so the container environment is defined rather than improvised.

And there is one line of advice that tells you about the code quality expectations. To catch a sanitizer in your IDE, set a breakpoint on __asan::ReportGenericError. That function is the AddressSanitizer's generic error reporter, and breaking on it in a debugger turns a sanitizer report into a stop you can inspect, which is a much better experience than reading the message afterwards.

The .gitmodules file and the emsdk and wasm directories in the tree also suggest that some of the tooling is compiled to WebAssembly, which is a fairly common technique for a piece of C code that needs to run in a build tool.

## Conclusion

Adopt teddycloud if you own a Toniebox and want its audio and configuration to stay on hardware you control, and if you are willing to run a container and a reverse proxy in front of it. Do not adopt it as a general product, since it implements one specific device's cloud protocol, and do not expect the documented web features to cover everything the manufacturer does, because the list of implemented capabilities is explicit. Before you start, clone with the submodules, build from the develop branch rather than master, and read the guide on the project website, because the configuration is not self-explanatory and the guide is where the setup detail lives.

## FAQ

### What is TeddyCloud?

It is an open source server replacement for the Boxine Cloud, an alternative server for your Toniebox that lets you host the cloud services locally. That gives you control over which data reaches the original manufacturer's cloud and lets you host your own figurine audio files on a NAS or another server.

### What can teddycloud do?

The implemented list includes providing audio content over the air, caching original tonie audio, simulating live content with .live, passing through original audio, converting audio files and streams to the tonie format with ffmpeg, filtering custom tags with .nocloud, configuring volume, the LED and the slapping behaviour, customising box sounds, extracting and injecting certificates on an esp32 firmware dump, decoding RTNL logs, an MQTT client and a Home Assistant integration over MQTT.

### Why does the teddycloud contribution workflow involve two repositories?

The backend and the web frontend, teddycloud_web, are separate repositories and the frontend is a submodule. Backend-only changes go to one pull request, frontend-only changes to the other, and changes in both need two separate pull requests, with the frontend merged first, and submodule pointer changes must not be committed in the backend pull request.

### How do I build and develop teddycloud?

Use the develop branch for development and pull requests, with stable builds on master, and clone with --recurse-submodules. The dev-sandbox directory runs the project locally with mock data, and in VS Code you build with the Run Task action and debug with F5, which starts bin/teddycloud under gdb with the prelaunch build.

### What are the current limitations of teddycloud?

The Planned section lists teddyBench integration and Toniebox 2 support, so the current target is the first generation of the device. The Docker image also ships with the sanitizers enabled by default, and the image exposes ports 80, 443 and 8443, so it is meant to run behind a reverse proxy rather than directly on the internet.

## Sources

- [License: GPL-2.0](https://github.com/toniebox-reverse-engineering/teddycloud/blob/master/LICENSE)
- [Project website](https://toniebox-reverse-engineering.github.io/docs/tools/teddycloud/)
- [README](https://github.com/toniebox-reverse-engineering/teddycloud/blob/master/README.md)
- [Releases](https://github.com/toniebox-reverse-engineering/teddycloud/releases)
- [toniebox-reverse-engineering/teddycloud on GitHub](https://github.com/toniebox-reverse-engineering/teddycloud)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/toniebox-reverse-engineering-teddycloud
