Skip to content

Cup

Monitoring des mises à jour d'images Docker sur l'ensemble de l'infrastructure.

Informations

Paramètre Valeur
URL https://updates.ncls.ltd (Authelia one_factor)
URL locale http://192.168.1.101:8000
Port 8000
Image ghcr.io/sergi0g/cup:latest
LXC LXC 101 – Management (serveur) + agents sur tous LXC
Config /opt/docker/cup/cup.json
API http://192.168.1.101:8000/api/v3/json

Architecture

Cup utilise un modèle serveur + agents pour couvrir tous les LXC :

Rôle LXC IP:Port Containers surveillés
Serveur 101 192.168.1.101:8000 Web UI, agrège locaux + tous les agents
Agent 100 192.168.1.100:8000 jellyfin, sonarr, radarr, bazarr, sabnzbd…
Agent 103 192.168.1.103:8000 caddy, authelia, wireguard, portainer-agent
Agent 104 192.168.1.104:8000 endurain, freshrss, romm, gramps, portainer-agent
Agent 105 192.168.1.105:8000 sites wordpress (asc, lmdp, nliautaud)
Agent 106 192.168.1.106:8000 sftpgo

Configuration Docker

Serveur (LXC 101, dans docker-compose.yaml) :

cup:
    container_name: cup
    image: ghcr.io/sergi0g/cup:latest
    restart: unless-stopped
    command: -c /config/cup.json serve -p 8000
    ports:
        - "8000:8000"
    volumes:
        - /var/run/docker.sock:/var/run/docker.sock:ro
        - /opt/docker/cup/cup.json:/config/cup.json:ro
    environment:
        - TZ=Europe/Paris

Agent (chaque autre LXC, dans leur docker-compose.yml) :

cup:
    container_name: cup
    image: ghcr.io/sergi0g/cup:latest
    restart: unless-stopped
    command: serve -p 8000
    ports:
        - "8000:8000"
    volumes:
        - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
        - CUP_AGENT=true
        - TZ=Europe/Paris

Important (bug #157) : L'agent Cup LXC 103 n'a intentionnellement aucun networks:. Rejoindre le réseau proxy du LXC 103 provoque un crash au démarrage.

Configuration cup.json

Path : /opt/docker/cup/cup.json

{
  "$schema": "https://raw.githubusercontent.com/sergi0g/cup/main/cup.schema.json",
  "version": 3,
  "refresh_interval": "0 0 */6 * * *",
  "servers": {
    "LXC 100 - Médias":    "http://192.168.1.100:8000",
    "LXC 103 - Réseau":    "http://192.168.1.103:8000",
    "LXC 104 - Services":  "http://192.168.1.104:8000",
    "LXC 105 - Web":       "http://192.168.1.105:8000",
    "LXC 106 - Stockage":  "http://192.168.1.106:8000"
  }
}

Le refresh automatique s'exécute toutes les 6h (cron 6 champs avec secondes obligatoires).

Homepage Widget

Widget customapi dans services.yaml :

widget:
    type: customapi
    url: http://192.168.1.101:8000/api/v3/json
    refreshInterval: 30000
    method: GET
    mappings:
        - field: metrics.monitored_images
          label: Monitored
          format: number
        - field: metrics.up_to_date
          label: Up to date
          format: number
        - field: metrics.updates_available
          label: Updates
          format: number

Cup et Renovate — coexistence

Depuis mai 2026, l'infrastructure utilise Renovate pour les mises à jour GitOps. Cup reste complémentaire mais leurs périmètres diffèrent :

Cup Renovate
Source Containers en cours d'exécution (docker.sock) Fichiers docker-compose.yml dans le monorepo git
Images :latest, :lts ✅ Détecte les changements de digest ❌ Ignoré intentionnellement
Images semver épinglées ✅ Détecte la nouvelle version ✅ Ouvre une PR automatiquement
zensical/zensical ✅ Visible ⚠️ PR créée, label needs-review
Action Information uniquement (UI) PR + merge + deploy automatisé

En pratique : Cup peut afficher beaucoup d'"updates" que Renovate n'ouvre pas en PR. C'est normal. Les mises à jour de digest sur :latest sont exclues du pipeline GitOps par design — elles n'ont pas de version sémantique à bumper.

Pour les images hors pipeline GitOps (:latest, services hors monorepo), la mise à jour reste manuelle si nécessaire.

Pour l'explication complète, voir Mise à jour Docker.

Maintenance

# Voir les updates disponibles (API JSON)
pct exec 101 -- curl -s http://localhost:8000/api/v3/json | \
  python3 -c "
import json, sys
d = json.load(sys.stdin)
for img in d['images']:
    r = img.get('result', {})
    if r.get('has_update'):
        print(f'  [{img.get(\"server\") or \"local\"}] {img[\"reference\"]} → {r[\"info\"]}')"

# Métriques globales
pct exec 101 -- curl -s http://localhost:8000/api/v3/json | \
  python3 -c "import json,sys; print(json.load(sys.stdin)['metrics'])"

# Logs serveur
pct exec 101 -- docker logs cup --tail 30

# Forcer un refresh (redémarrer le serveur)
pct exec 101 -- docker restart cup

# Mettre à jour Cup lui-même
pct exec 101 -- bash -c "cd /opt/docker && docker compose pull cup && docker compose up -d cup"

# Status agents
for lxc in 100 103 104 105 106; do
  echo -n "LXC $lxc: "
  pct exec $lxc -- docker ps --filter name=cup --format "{{.Status}}" 2>/dev/null
done

Notes

  • LXC 103 utilise l'image Cup depuis Zot : 192.168.1.107:5000/ghcr/sergi0g/cup:3.5.1 — pas d'export/import manuel nécessaire depuis la mise en place de Zot.