Files
L'électron rare f55093d6fe
ESP-IDF CI / Host Tests (Unity) (push) Successful in 1m8s
CI / firmware-native (push) Successful in 2m57s
Rust Protection Tests / Cargo test (host) (push) Failing after 3m21s
ESP-IDF CI / ESP-IDF Build (v5.4) (push) Failing after 6m55s
ESP-IDF CI / Memory Budget Gate (push) Has been skipped
qa-cicd-environments / qa-kxkm-s3-build (push) Successful in 8m53s
qa-cicd-environments / qa-sim-host (push) Successful in 2m2s
qa-cicd-environments / qa-kxkm-s3-memory-budget (push) Successful in 11m17s
chore: import KXKM Batterie Parallelator
Context: the project archive (KXKM_Batterie_Parallelator-main) had
no git history locally; a fresh repository is needed to host it on
git.saillant.cc (electron/KXKM_Batterie_Parallelator).

Approach: initialize a new repo on branch main, stage the archive
content, and harden .gitignore before the first commit.

Changes:
- Import the full project tree: firmware/, firmware-idf/,
  firmware-rs/, iosApp/, kxkm-bmu-app/, kxkm-api/, hardware/,
  docs/, specs/, scripts/, models/, tests/
- Keep project dotfiles tracked despite the trailing '.*' ignore
  rule: .github/, .claude/, .superpowers/, .gitattributes,
  .markdownlint.json
- Extend .gitignore: firmware/src/credentials.h (local secrets,
  template kept), kxkm-bmu-app/**/build/ (66 MB compiled iOS
  framework), .remember/ (session data)

Impact: the project can now be maintained on the self-hosted Gitea
forge with a clean, secret-free initial history.
2026-07-04 12:32:28 +02:00

3.6 KiB

Déploiement bmu.saillant.cc

Page de supervision publique (lecture seule) du BMU.

Architecture

Navigateur ──https──▶ Cloudflare ──▶ nginx public (hôte saillant.cc)
                                       ├─ /            → page statique (web/)
                                       └─ /api/ (GET)  → proxy Tailscale ─▶ VM kxkm-bmu:8400
                                                          (+ Authorization: Bearer <clé>)

La clé API reste côté nginx ; le navigateur ne la voit jamais. Tout est servi sous bmu.saillant.cc → pas de CORS.

Prérequis

  1. Tailscale sur la VM : tailscale up exécuté sur kxkm-bmu (10.2.5.110). Récupérer l'IP : tailscale ip -4 (ou nom MagicDNS kxkm-bmu).
  2. Connectivité : l'hôte nginx public doit être dans le même tailnet.
  3. DNS : enregistrement bmu.saillant.cc → hôte nginx (Cloudflare, proxied pour le TLS).

Étapes

# 1. Backend : redéployer l'API (nouveaux endpoints climate/solar) sur la VM
#    (depuis le repo, via le jump host — cf. project_kxkm_bmu_backend_vm)
#    rsync/tar kxkm-api/ → VM puis : docker compose up -d --build bmu-api

# 2. Page statique → hôte nginx public
sudo mkdir -p /var/www/bmu.saillant.cc
sudo cp kxkm-api/web/index.html /var/www/bmu.saillant.cc/

# 3. Vhost nginx
sudo cp kxkm-api/deploy/bmu.saillant.cc.nginx.conf /etc/nginx/sites-available/bmu.saillant.cc
#    éditer : <VM_TS_ADDR> = IP Tailscale de la VM, <BMU_API_KEY> = clé de ~/kxkm-api/.env
sudo ln -sf /etc/nginx/sites-available/bmu.saillant.cc /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

Vérification

curl -s https://bmu.saillant.cc/api/bmu/batteries | head    # via le proxy (clé injectée)
# la page : https://bmu.saillant.cc

Déploiement réel (saillant.cc — Docker/Traefik/Cloudflare Tunnel)

L'infra saillant.cc n'utilise pas un nginx hôte mais Traefik + conteneurs nginx:alpine par site sur electron-server (tailnet), derrière un Cloudflare Tunnel (remotely-managed). Setup effectif :

# Sur electron-server ([email protected], dans le tailnet) :
#   ~/saillant-sites/bmu-static/index.html           ← la page
#   ~/saillant-sites/bmu-overrides/default.conf       ← nginx (page + proxy /api)
# Conteneur :
docker run -d --name bmu-saillant --restart unless-stopped --network traefik \
  -v ~/saillant-sites/bmu-overrides/default.conf:/etc/nginx/conf.d/default.conf:ro \
  -v ~/saillant-sites/bmu-static:/usr/share/nginx/html:ro \
  -l traefik.enable=true -l traefik.docker.network=traefik \
  -l 'traefik.http.routers.bmu-saillant.entrypoints=websecure' \
  -l 'traefik.http.routers.bmu-saillant.rule=Host(`bmu.saillant.cc`)' \
  -l 'traefik.http.routers.bmu-saillant.tls.certresolver=letsencrypt' \
  -l 'traefik.http.services.bmu-saillant.loadbalancer.server.port=80' \
  nginx:alpine

Le default.conf proxy /api/ vers http://100.74.48.9:8400 (IP Tailscale de la VM kxkm-bmu) avec Authorization: Bearer <clé> injecté.

Dernière étape (Cloudflare Zero Trust dashboard) : ajouter un Public Hostname au tunnel → bmu.saillant.cc avec la même config de service que zacus.saillant.cc (le tunnel route par hostname ; sans cette entrée Cloudflare renvoie 404 alors que l'origine répond 200).

Endpoints exposés (GET, lecture seule via proxy)

  • /api/bmu/batteries — état courant des batteries + parc
  • /api/bmu/climate · /api/bmu/climate/history?from=-24h
  • /api/bmu/solar · /api/bmu/solar/history?from=-24h
  • /api/bmu/history?from=-24h[&battery=N] — séries batteries
  • /api/bmu/audit — journal (si exposé)