# 🕐 CronHub **CronHub** est un gestionnaire de cron jobs avec interface web et API REST, auto-hĂ©bergĂ© sur NAS. 🌐 **URL** : [https://cronhub.nas.percolouco.com](https://cronhub.nas.percolouco.com) --- ## 📋 Description CronHub permet de crĂ©er, gĂ©rer et monitorer des tĂąches planifiĂ©es (cron jobs) depuis une interface web simple et intuitive. Chaque job est exĂ©cutĂ© via `nsenter` dans le namespace de l'hĂŽte Docker, avec capture des logs (stdout/stderr) et historique d'exĂ©cution. > **NouveautĂ©** : les commandes sont dĂ©sormais exĂ©cutĂ©es via `nsenter --target 1 --mount --uts --ipc --net --pid`, ce qui donne accĂšs complet Ă  l'environnement hĂŽte (python3, npm, openclaw, etc.). --- ## đŸ› ïž Stack technique | Composant | Technologie | |-----------|-------------| | Backend / API | [FastAPI](https://fastapi.tiangolo.com/) | | Scheduler | [APScheduler 3.x](https://apscheduler.readthedocs.io/) | | Base de donnĂ©es | SQLite (WAL mode) | | Templates UI | Jinja2 | | CSS | Tailwind CSS (via CDN) + styles custom | | Serveur ASGI | Uvicorn | | Containerisation | Docker | --- ## ✹ FonctionnalitĂ©s - **CRUD complet** — CrĂ©er, lire, modifier, supprimer des jobs - **CatĂ©gories** — Champ `category` sur chaque job ; filtre par catĂ©gorie dans l'UI + colonne dĂ©diĂ©e dans le tableau - **Toggle actif/inactif** — Activer ou dĂ©sactiver un job sans le supprimer - **Run immĂ©diat** — DĂ©clencher un job manuellement hors schedule - **Logs d'exĂ©cution** — Historique complet avec stdout, stderr, exit code, durĂ©e - **Statuts visuels** — Dashboard avec compteurs (total, actifs, succĂšs, Ă©checs) - **API Swagger** — Documentation interactive disponible sur `/docs` - **Timezone** — Europe/Paris (configurable via `TZ`) - **Persistance** — SQLite dans volume Docker `/data` - **AccĂšs hĂŽte** — ExĂ©cution via `nsenter` pour accĂ©der Ă  python3, npm, openclaw et tous les outils de l'hĂŽte --- ## 📊 Jobs configurĂ©s | CatĂ©gorie | Nombre | Exemples | |-----------|--------|---------| | SystĂšme / MH / Plex / Location | 11 | Backups, monitoring, rapports Plex | | Potager / Maison | 24 | Arrosage, alertes, automatisations maison | | Sync | 1 | Synchronisation Gitea → GitHub | ### 🔄 Job de synchronisation Gitea → GitHub Un job automatique synchronise tous les dĂ©pĂŽts de Gitea (`http://192.168.1.29:3500/perco`) vers GitHub (`percolouco`) : - **FrĂ©quence** : Toutes les heures (`0 * * * *`) - **Mode** : Mirror (toutes les branches et tags) - **Scripts** : Voir `scripts/README_SYNC.md` pour la configuration complĂšte - **Tokens requis** : `GITHUB_TOKEN` et `GITEA_TOKEN` (configurĂ©s comme secrets) --- ## 🔌 API Endpoints ### SantĂ© | MĂ©thode | Route | Description | |---------|-------|-------------| | `GET` | `/api/health` | VĂ©rification de l'Ă©tat de l'API | ### Jobs | MĂ©thode | Route | Description | |---------|-------|-------------| | `GET` | `/api/jobs` | Lister tous les jobs | | `POST` | `/api/jobs` | CrĂ©er un job | | `GET` | `/api/jobs/{id}` | DĂ©tail d'un job | | `PUT` | `/api/jobs/{id}` | Modifier un job | | `DELETE` | `/api/jobs/{id}` | Supprimer un job | | `POST` | `/api/jobs/{id}/toggle` | Activer/dĂ©sactiver un job | | `POST` | `/api/jobs/{id}/run` | DĂ©clencher un job manuellement | | `GET` | `/api/jobs/{id}/logs` | Logs d'exĂ©cution d'un job | ### UI (HTML) | MĂ©thode | Route | Description | |---------|-------|-------------| | `GET` | `/` | Dashboard principal | | `GET` | `/jobs/new` | Formulaire crĂ©ation | | `GET` | `/jobs/{id}` | DĂ©tail + logs UI | | `GET` | `/jobs/{id}/edit` | Formulaire Ă©dition | | `POST` | `/jobs/{id}/run-now` | Run immĂ©diat (UI) | | `GET` | `/docs` | Documentation Swagger | ### Exemple d'appel API ```bash # CrĂ©er un job avec catĂ©gorie curl -X POST https://cronhub.nas.percolouco.com/api/jobs \ -H "Content-Type: application/json" \ -d '{ "name": "Mon backup", "schedule": "0 3 * * *", "command": "/scripts/backup.sh", "description": "Backup quotidien Ă  3h", "category": "systĂšme", "enabled": true }' # Lister les jobs curl https://cronhub.nas.percolouco.com/api/jobs # Mettre Ă  jour la catĂ©gorie d'un job curl -X PUT https://cronhub.nas.percolouco.com/api/jobs/{id} \ -H "Content-Type: application/json" \ -d '{"category": "potager"}' # DĂ©clencher manuellement curl -X POST https://cronhub.nas.percolouco.com/api/jobs/{id}/run # Consulter les logs curl https://cronhub.nas.percolouco.com/api/jobs/{id}/logs?limit=20 ``` --- ## đŸ—‚ïž Structure du projet ``` cronhub/ ├── app/ │ ├── __init__.py │ └── main.py # Application FastAPI (routes, scheduler, DB) ├── scripts/ │ ├── sync_gitea_to_github.py # Script de synchronisation Gitea → GitHub │ ├── init_sync_job.py # Initialisation du job de sync dans CronHub │ └── README_SYNC.md # Documentation du systĂšme de sync ├── templates/ │ ├── index.html # Dashboard (avec filtre par catĂ©gorie) │ ├── job_detail.html # DĂ©tail d'un job + logs │ └── job_form.html # Formulaire crĂ©ation/Ă©dition (champ category) ├── data/ # Volume persistant (SQLite) ├── Dockerfile ├── docker-compose.yml └── requirements.txt ``` --- ## 🐳 Installation Docker ### PrĂ©requis - Docker + Docker Compose - (Optionnel) Traefik comme reverse proxy ### docker-compose.yml ```yaml version: "3.8" services: cronhub: build: . container_name: cronhub restart: unless-stopped privileged: true # Requis pour nsenter pid: host # AccĂšs au namespace PID de l'hĂŽte volumes: - ./data:/data # Persistance SQLite - /opt/container/cronmaster/scripts:/scripts:ro # Scripts montĂ©s en lecture seule - /var/run/docker.sock:/var/run/docker.sock # AccĂšs Docker environment: - DB_PATH=/data/cronhub.db - TZ=Europe/Paris networks: - proxy labels: - "traefik.enable=true" - "traefik.http.routers.cronhub.rule=Host(`cronhub.nas.percolouco.com`)" - "traefik.http.routers.cronhub.entrypoints=websecure" - "traefik.http.routers.cronhub.tls=true" - "traefik.http.routers.cronhub.tls.certresolver=letsencrypt" - "traefik.http.services.cronhub.loadbalancer.server.port=8000" networks: proxy: external: true ``` > **Important** : `privileged: true` et `pid: host` sont nĂ©cessaires pour que `nsenter` puisse accĂ©der aux namespaces de l'hĂŽte. ### DĂ©marrage ```bash cd /opt/container/cronhub docker compose up -d --build ``` ### Variables d'environnement | Variable | DĂ©faut | Description | |----------|--------|-------------| | `DB_PATH` | `/data/cronhub.db` | Chemin de la base SQLite | | `TZ` | `Europe/Paris` | Timezone pour le scheduler | --- ## 📩 ModĂšle de donnĂ©es ### Job ```json { "id": "uuid", "name": "Mon job", "schedule": "0 8 * * *", "command": "python3 /opt/mon-script.py", "description": "Description optionnelle", "category": "potager", "enabled": true, "last_run": "2026-03-15T08:00:00", "last_status": "success", "created_at": "2026-03-01T12:00:00" } ``` ### Log d'exĂ©cution ```json { "id": 42, "job_id": "uuid", "started_at": "2026-03-15T08:00:00", "ended_at": "2026-03-15T08:00:01", "status": "success", "exit_code": 0, "stdout": "...", "stderr": "" } ``` --- ## 🔧 Notes de dĂ©ploiement - Les commandes sont exĂ©cutĂ©es via `nsenter --target 1 --mount --uts --ipc --net --pid` — accĂšs complet Ă  l'environnement hĂŽte (python3, npm, openclaw, etc.) - `privileged: true` et `pid: host` sont requis dans le `docker-compose.yml` - Les scripts dans `/scripts` sont montĂ©s depuis `/opt/container/cronmaster/scripts` (lecture seule) - Le scheduler APScheduler dĂ©marre automatiquement au lancement et recharge tous les jobs actifs - Les jobs sont exĂ©cutĂ©s en `shell=True` avec un timeout de 3600 secondes - Stdout/stderr sont limitĂ©s Ă  10 000 caractĂšres par exĂ©cution --- ## 📄 Licence Projet privĂ© — perco / NAS domestique