OPS

Deploy & Ops

systemd · Docker · monitoring · checklist

Stack — Qué Corre Dónde

 ┌─────────────────────────────────────────────────────┐
 │              RPi 3B — Yocto Poky 4.3.4              │
 │              └─ Docker (Bookworm container)          │
 │                                                      │
 │  systemd                                             │
 │  ├── murmurd.service      (:64738)  ← ya existente  │
 │  ├── ustreamer.service    (:8080)   ← NUEVO         │
 │  └── oasis.service        (:3000)   ← ya existente  │
 │       └── audio-bridge    (interno)                  │
 │       └── node-datachannel (interno)                 │
 └─────────────────────────────────────────────────────┘

systemd Units — Copy-Paste Ready

ustreamer.service (NUEVO)
# /etc/systemd/system/ustreamer.service [Unit] Description=µStreamer MJPEG server After=network.target [Service] Type=simple User=video ExecStartPre=/sbin/modprobe bcm2835-v4l2 ExecStart=/usr/bin/ustreamer \ --host 127.0.0.1 \ --port 8080 \ --encoder=m2m-image \ --workers=3 \ --resolution=1280x720 \ --desired-fps=15 \ --drop-same-frames=20 Restart=on-failure RestartSec=5 StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target
Para cámara USB: quitar ExecStartPre, cambiar --encoder a cpu, añadir --device=/dev/video0
Habilitar y arrancar
sudo systemctl daemon-reload sudo systemctl enable --now ustreamer.service sudo systemctl status ustreamer.service

Docker — Integración con Container Bookworm

El SNH corre Yocto Poky 4.3.4 como host, con un container Docker Debian Bookworm. µStreamer corre dentro del container pero necesita acceso a /dev/video* del host.
# docker-compose.yml (fragmento) services: snh: image: snh-bookworm:latest devices: - /dev/video0:/dev/video0 # cámara - /dev/video11:/dev/video11 # M2M encoder (si CSI) ports: - "3000:3000" # Oasis (único puerto público) # µStreamer :8080 y murmurd :64738 son solo internos volumes: - mumble-data:/var/lib/mumble cap_add: - SYS_RAWIO # para V4L2 M2M si es necesario
No exponer :8080 ni :64738 en ports. Solo :3000 sale al exterior. Los servicios internos se comunican via localhost dentro del container.
Verificar devices dentro del container
docker exec -it snh ls -la /dev/video* docker exec -it snh v4l2-ctl --list-devices

Monitoring — Health Checks

Script de health check (crontab cada 5 min)
#!/bin/bash — /usr/local/bin/snh-health.sh # Video: µStreamer alive? curl -sf http://127.0.0.1:8080/state > /dev/null \ || systemctl restart ustreamer.service # Audio: murmurd alive? ss -tlnp | grep -q :64738 \ || systemctl restart mumble-server.service # Oasis: alive? curl -sf http://127.0.0.1:3000/ > /dev/null \ || systemctl restart oasis.service
Crontab entry
crontab -e */5 * * * * /usr/local/bin/snh-health.sh 2>&1 | logger -t snh-health
RAM monitoring (alerta si <100 MB libre)
# En snh-health.sh, añadir: FREE_MB=$(free -m | awk '/^Mem:/{print $7}') if [ "$FREE_MB" -lt 100 ]; then logger -t snh-health -p warning "LOW RAM: ${FREE_MB}MB free" fi

Pre-Flight Checklist

#CheckComandoEsperado
1Cámara detectadav4l2-ctl --list-devices/dev/video0 aparece
2M2M encoder (CSI)ls /dev/video1*/dev/video11 (bcm2835-codec)
3User en grupo videogroups"video" aparece
4µStreamer instaladowhich ustreamer/usr/bin/ustreamer
5µStreamer arrancacurl localhost:8080/stateJSON con fps > 0
6MJPEG streamcurl -I localhost:8080/stream200 + multipart/*
7murmurd activoss -tlnp | grep 64738LISTEN
8Oasis activocurl -I localhost:3000200
9Proxy videocurl -I localhost:3000/video200 + multipart/*
10RAM availablefree -m | awk '/Mem/{print $7}'> 200 MB

Boot Order — Dependencias

  [kernel modules]
       │ modprobe bcm2835-v4l2 + bcm2835-codec
       ▼
  [murmurd]  ← ya existente, sin deps nuevas
       │
  [ustreamer] ← After=network.target
       │
  [oasis]     ← After=ustreamer.service mumble-server.service
       ├── audio-bridge (child process)
       └── node-datachannel (in-process)
Añadir After=ustreamer.service mumble-server.service en oasis.service para que el proxy no falle al arrancar antes que los upstreams.

Logs — Comandos Útiles

# Ver logs de µStreamer journalctl -u ustreamer -f --no-pager # Ver logs de murmurd journalctl -u mumble-server -f --no-pager # Ver logs de Oasis journalctl -u oasis -f --no-pager # Ver health checks journalctl -t snh-health --since "1 hour ago" # RAM snapshot free -m && ps aux --sort=-%mem | head -10

Keywords

systemd ExecStart Docker devices modprobe crontab journalctl health check V4L2 Yocto Bookworm free -m