Compare commits
2 Commits
claude/cha
...
claude/jol
| Author | SHA1 | Date | |
|---|---|---|---|
| a45e4f6f29 | |||
| 77b3a6f677 |
112
containers/131-teddycloud.md
Normal file
112
containers/131-teddycloud.md
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
# 131 — `teddycloud`
|
||||||
|
|
||||||
|
Open-source replacement server for Toniebox smart audio devices (Tonieboxes). Serves device content and API on port 443 and exposes a management web UI at `teddy.hubris.network`.
|
||||||
|
|
||||||
|
## At a glance
|
||||||
|
|
||||||
|
- **Hostname:** `teddycloud`
|
||||||
|
- **IP:** `192.168.8.243` (DHCP reservation; MAC `bc:24:11:11:7a:df`)
|
||||||
|
- **Privilege:** privileged
|
||||||
|
- **Resources:** 1 core / 1 GiB RAM / 16 GiB rootfs (Debian 12)
|
||||||
|
- **Mounts:** `/mnt/library` (`mp0`) — TeddyCloud content at `/mnt/library/cloud/leon`
|
||||||
|
- **Public hostname:** none (LAN-only)
|
||||||
|
|
||||||
|
## Role
|
||||||
|
|
||||||
|
Replaces the Boxine cloud (`prod.de.bb-online.com`) as the backend for Leon's Toniebox. Tonieboxes connect on port 443 using a custom CA cert issued by TeddyCloud. Content (Tonies) is stored on the NAS at `/mnt/library/cloud/leon` and is accessible from the management UI.
|
||||||
|
|
||||||
|
## Service / port map
|
||||||
|
|
||||||
|
| Service | Listen | Notes |
|
||||||
|
|---------|--------|-------|
|
||||||
|
| TeddyCloud device API | `0.0.0.0:443` | HTTPS, TeddyCloud self-signed CA, Toniebox connects here |
|
||||||
|
| TeddyCloud HTTP | `0.0.0.0:80` | Redirects to 443 |
|
||||||
|
| TeddyCloud web UI | `0.0.0.0:8443` | HTTPS management UI — fronted by Caddy at `teddy.hubris.network` (backend uses `tls_insecure_skip_verify` for self-signed cert on LAN hop) |
|
||||||
|
|
||||||
|
## Docker Compose
|
||||||
|
|
||||||
|
`/opt/teddycloud/docker-compose.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
teddycloud:
|
||||||
|
image: ghcr.io/toniebox-reverse-engineering/teddycloud:latest
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
- "8443:8443"
|
||||||
|
volumes:
|
||||||
|
- certs:/teddycloud/certs
|
||||||
|
- config:/teddycloud/config
|
||||||
|
- /mnt/library/cloud/leon:/teddycloud/content
|
||||||
|
- /mnt/library/cloud/leon:/teddycloud/library
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
certs:
|
||||||
|
config:
|
||||||
|
```
|
||||||
|
|
||||||
|
`certs` and `config` are Docker named volumes (runtime state). `content` and `library` are bind-mounted from `/mnt/library/cloud/leon` so audio content persists across container rebuilds and is browsable from the host.
|
||||||
|
|
||||||
|
## Storage / config paths
|
||||||
|
|
||||||
|
- `/opt/teddycloud/docker-compose.yml` — compose file
|
||||||
|
- Docker volume `teddycloud_certs` — TeddyCloud CA + server certs (generated on first boot)
|
||||||
|
- Docker volume `teddycloud_config` — TeddyCloud config
|
||||||
|
- `/mnt/library/cloud/leon/` — Tonie content + library (NAS bind mount)
|
||||||
|
|
||||||
|
## Networking
|
||||||
|
|
||||||
|
Two separate traffic paths — different IPs, no port 443 conflict:
|
||||||
|
|
||||||
|
**Management UI (browser):**
|
||||||
|
```
|
||||||
|
teddy.hubris.network → Technitium → 192.168.8.175 (Caddy) → 192.168.8.243:8443
|
||||||
|
```
|
||||||
|
|
||||||
|
**Toniebox device traffic:**
|
||||||
|
```
|
||||||
|
prod.de.bb-online.com → Technitium override → 192.168.8.243:443 (TeddyCloud direct)
|
||||||
|
```
|
||||||
|
|
||||||
|
Caddy terminates TLS for the management UI (IONOS DNS-01 wildcard cert). TeddyCloud terminates TLS for device traffic with its own self-signed CA — the Toniebox must have this CA installed.
|
||||||
|
|
||||||
|
### DNS overrides in Technitium
|
||||||
|
|
||||||
|
| Record | Type | Value | Purpose |
|
||||||
|
|--------|------|-------|---------|
|
||||||
|
| `teddy.hubris.network` | A | `192.168.8.175` | Management UI → Caddy (standard pattern) |
|
||||||
|
| `prod.de.bb-online.com` | A | `192.168.8.243` | Toniebox device traffic → TeddyCloud direct |
|
||||||
|
|
||||||
|
The `prod.de.bb-online.com` override is Technitium-only — it intercepts Toniebox DNS locally without touching public DNS. The `dns-sync.py` cron on LXC 107 skips non-`hubris.network` records, so it stays local.
|
||||||
|
|
||||||
|
## Config notes
|
||||||
|
|
||||||
|
- `core.boxCertAuth=false` — client cert validation disabled. The box connects without presenting its unique client cert. Set in `/var/lib/docker/volumes/teddycloud_config/_data/config.ini` (TeddyCloud hot-reloads on change).
|
||||||
|
- If you ever want per-box auth, flip to `true` and supply `certs/client/ca.der`, `client.der`, `private.der` extracted from the box flash.
|
||||||
|
|
||||||
|
## Toniebox onboarding — ESP32 SD card method
|
||||||
|
|
||||||
|
Leon's box is ESP32 generation. No hardware mod required.
|
||||||
|
|
||||||
|
1. Download the TeddyCloud CA cert from the web UI: **Security → CA Certificate → Download CA** (`ca.der`).
|
||||||
|
2. Power off the Toniebox, remove the SD card.
|
||||||
|
3. On the SD card, create folder `cert/` at the root.
|
||||||
|
4. Copy the downloaded `ca.der` into `cert/ca.der` on the SD card.
|
||||||
|
5. Reinsert SD card, power on the box.
|
||||||
|
6. The box patches itself to trust TeddyCloud's CA, then resolves `prod.de.bb-online.com` via Technitium's override (`192.168.8.243`) and connects on port 443.
|
||||||
|
|
||||||
|
Reference: [upstream wiki — ESP32 SD card method](https://github.com/toniebox-reverse-engineering/teddycloud/wiki).
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [Caddy (121)](121-caddy.md) — LAN reverse proxy (`teddy.hubris.network → 192.168.8.243:8443`)
|
||||||
|
- [DNS (107)](../infrastructure/dns.md) — Technitium A records for `teddy.hubris.network` and `prod.de.bb-online.com`
|
||||||
|
- [Media permissions](../infrastructure/media-permissions.md) — NAS `/mnt/library` mount pattern
|
||||||
|
|
||||||
|
## Changelog
|
||||||
|
|
||||||
|
### 2026-06-29 — provisioned
|
||||||
|
|
||||||
|
LXC 131 created (Debian 12, privileged, nesting=1). Docker installed. TeddyCloud running via Docker Compose at `/opt/teddycloud/`. Content bind-mounted from `/mnt/library/cloud/leon`. Caddy block added at `teddy.hubris.network → :8443`. Technitium A records: `teddy.hubris.network → 192.168.8.175` (Caddy), `prod.de.bb-online.com → 192.168.8.243` (device traffic direct).
|
||||||
@@ -18,6 +18,7 @@ All containers live on [`hubris`](../hosts/hubris.md). Each row links to the per
|
|||||||
| 128 | [trmnl](128-trmnl.md) | 192.168.8.211 | unpriv | 1 | 768 MiB | 8 GiB | — | `trmnl.hubris.network` | running |
|
| 128 | [trmnl](128-trmnl.md) | 192.168.8.211 | unpriv | 1 | 768 MiB | 8 GiB | — | `trmnl.hubris.network` | running |
|
||||||
| 129 | [house](129-house.md) | 192.168.8.212 | unpriv | 1 | 1344 MiB | 8 GiB | — | `house.hubris.network` | running |
|
| 129 | [house](129-house.md) | 192.168.8.212 | unpriv | 1 | 1344 MiB | 8 GiB | — | `house.hubris.network` | running |
|
||||||
| 130 | [grimmory](130-grimmory.md) | 192.168.8.213 | priv | 1 | 2 GiB | 16 GiB | `/mnt/library` | `books.hubris.network` | running |
|
| 130 | [grimmory](130-grimmory.md) | 192.168.8.213 | priv | 1 | 2 GiB | 16 GiB | `/mnt/library` | `books.hubris.network` | running |
|
||||||
|
| 131 | [teddycloud](131-teddycloud.md) | 192.168.8.243 | priv | 1 | 1 GiB | 16 GiB | `/mnt/library` | `teddy.hubris.network` (LAN only) | running |
|
||||||
|
|
||||||
## Recently destroyed (kept for archaeology)
|
## Recently destroyed (kept for archaeology)
|
||||||
|
|
||||||
|
|||||||
@@ -33,9 +33,18 @@ address=/photos.hubris.network/192.168.8.175
|
|||||||
address=/photos-new.hubris.network/192.168.8.175
|
address=/photos-new.hubris.network/192.168.8.175
|
||||||
address=/artifacto.hubris.network/192.168.8.175
|
address=/artifacto.hubris.network/192.168.8.175
|
||||||
address=/zimaos.hubris.network/192.168.8.175
|
address=/zimaos.hubris.network/192.168.8.175
|
||||||
|
address=/teddy.hubris.network/192.168.8.175
|
||||||
address=/nfs-export.hubris.network/192.168.8.200
|
address=/nfs-export.hubris.network/192.168.8.200
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Non-`hubris.network` override (Toniebox device traffic):**
|
||||||
|
|
||||||
|
```
|
||||||
|
address=/prod.de.bb-online.com/192.168.8.243 # → TeddyCloud (131) direct on :443
|
||||||
|
```
|
||||||
|
|
||||||
|
This intercepts Toniebox DNS locally without touching public DNS. The `dns-sync.py` cron on LXC 107 skips non-`hubris.network` records — this entry is Technitium-only.
|
||||||
|
|
||||||
Note: `nfs-export.hubris.network` is the only `.hubris.network` entry that points to a non-HTTP service (NFSv4 on port 2049). It bypasses [caddy (121)](../containers/121-caddy.md) because NFS is L4, not HTTP — Caddy has nothing to do.
|
Note: `nfs-export.hubris.network` is the only `.hubris.network` entry that points to a non-HTTP service (NFSv4 on port 2049). It bypasses [caddy (121)](../containers/121-caddy.md) because NFS is L4, not HTTP — Caddy has nothing to do.
|
||||||
|
|
||||||
## Why split-horizon
|
## Why split-horizon
|
||||||
@@ -75,6 +84,9 @@ Either:
|
|||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
### 2026-06-29 — `teddy.hubris.network` added; `prod.de.bb-online.com` override added
|
||||||
|
TeddyCloud (LXC 131) provisioned. `teddy.hubris.network → 192.168.8.175` (Caddy → TeddyCloud web UI at :8443). Non-hubris override `prod.de.bb-online.com → 192.168.8.243` routes Toniebox device HTTPS traffic directly to TeddyCloud port 443 — this bypasses Caddy and is Technitium-only (dns-sync cron does not replicate non-hubris.network records to the NetBird managed zone).
|
||||||
|
|
||||||
### 2026-06-28 — `plato.hubris.network` removed
|
### 2026-06-28 — `plato.hubris.network` removed
|
||||||
Plato (LXC 126) decommissioned. Technitium entry deleted; dns-sync cron reaped the NetBird managed zone record.
|
Plato (LXC 126) decommissioned. Technitium entry deleted; dns-sync cron reaped the NetBird managed zone record.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user