Repository navigation
Runbooks and Scheduled Tasks
Deux mécanismes pour déclencher une action agent (apt/docker/systemd/journal/
processus/custom/restic) sans passer par un clic manuel à chaque fois. Ils
partagent le même composant de formulaire (DispatchStepEditor) mais
reposent sur des modèles de confiance très différents — c'est le point le
plus important à comprendre avant de choisir lequel utiliser.
Dashboard → Automatisation → Runbooks (admin uniquement, toute la section).
Un runbook est une suite ordonnée d'étapes, chacune ciblant un hôte et une action déjà whitelistée côté serveur :
| Champ (étape) | Rôle |
|---|---|
| Hôte | Cible de cette étape |
| Module |
docker / apt / systemd / journal / processes / custom
|
| Action | Dépend du module (voir tableau ci-dessous) |
Cible (target) |
Requis pour journal / systemd / custom, sinon optionnel |
| Continuer même si cette étape échoue | Décoché par défaut — une étape en échec arrête tout le runbook |
Actions whitelistées par module (identiques côté frontend et serveur — le serveur revalide indépendamment, le frontend ne fait que refléter la même liste) :
| Module | Actions autorisées |
|---|---|
docker |
logs, restart, start, stop, compose_up, compose_down, compose_pull, compose_logs, compose_restart
|
apt |
update, upgrade, full-upgrade, autoremove
|
systemd |
status, start, stop, restart, list
|
journal |
read |
processes |
list |
custom |
run |
restic n'est pas dans cette liste — un runbook ne peut pas déclencher
un backup Restic (voir §3).
Un runbook nécessite au moins une étape à la création (min=1 côté
validation serveur).
Manuel uniquement — pas de cron, pas de déclenchement par une règle
d'alerte. POST /api/v1/runbooks/:id/run ne dispatche que la première
étape. La progression est gérée en réaction à la fin de chaque commande :
si l'étape échoue et que continue_on_failure est décoché, l'exécution
entière passe failed ; sinon (succès, ou échec toléré) l'étape suivante
est dispatchée automatiquement. Plus d'étape suivante → exécution
completed.
Après un clic sur Exécuter, l'UI ouvre l'historique et interroge
GET .../executions toutes les 3 secondes jusqu'à un statut terminal — il
n'y a pas de flux push pour la progression multi-étapes, seul le résultat
de chaque commande individuelle est streamé en direct (bouton logs par
étape).
Dashboard → Tâches planifiées.
| Champ | Rôle |
|---|---|
| Hôte | Cible unique |
| Module |
apt / docker / systemd / journal / processes / custom / restic
|
| Action | Texte libre suggéré par une liste indicative selon le module — non validé côté serveur. Masqué et facultatif pour module=custom, où l'agent l'ignore entièrement (seul l'identifiant de tâche compte) |
Cible (target) |
Selon module (ex : nom de profil Restic, unité systemd, identifiant de tâche custom…) |
| Planification |
CronBuilder — mode Visuel (fréquence quotidienne/hebdo/mensuelle/personnalisée) ou Expert (cron brut à 5 champs, minute heure jour-du-mois mois jour-de-la-semaine) ; l'heure saisie est interprétée dans le fuseau du serveur, pas du navigateur — voir §2.4
|
| Exécution manuelle uniquement | Coché = pas de planification — voir §2.1 |
Il n'existe pas de colonne dédiée "manuel" en base : cocher cette case
force enabled=false et remplace l'expression cron par une sentinelle
(0 0 29 2 * — 29 février, ne se déclenche jamais). C'est purement une
convention frontend ; si vous interrogez l'API directement, une tâche
"manuelle" ressemble à une tâche désactivée avec un cron impossible, pas à
un type distinct.
Une tâche déclarée dans le tasks.yaml d'un hôte n'a pas besoin d'une tâche
planifiée pour être exécutée une fois : la fiche hôte a un onglet Tâches
personnalisées qui les liste (telles que l'agent les voit) avec un bouton
Exécuter — POST /api/v1/hosts/:id/custom-tasks/:taskId/run, Operator+
sur l'hôte, aucune ligne persistée dans scheduled_tasks.
Créez une tâche planifiée module=custom uniquement quand vous voulez
réellement une récurrence (ou une entrée réutilisable à déclencher d'un
clic). Pour un « lance-moi ça maintenant », l'onglet est le bon chemin —
c'est l'équivalent des boutons ad-hoc que docker/apt/systemd ont déjà.
Le sélecteur d'action bascule automatiquement en champ texte libre pour
tout module sans liste d'actions suggérées prédéfinie — c'est voulu, pas un
bug d'UI : le serveur ne validant pas action, l'UI ne peut de toute façon
pas prétendre connaître la liste exhaustive.
Le scheduler cron (robfig/cron) interprète les champs heure/minute de
chaque tâche dans le fuseau horaire du process serveur (time.Local),
pas dans celui du navigateur utilisé pour la créer. Sans configuration
explicite, le conteneur Docker tourne en UTC : une tâche planifiée pour
"23h00" via CronBuilder se déclenche réellement à 23h00 UTC, soit
01h00 le lendemain pour un opérateur en UTC+2 (heure d'été Europe/Paris) —
CronBuilder affiche un hint le rappelant, dans les deux modes (Visuel et
Expert).
Pour aligner l'exécution sur votre propre fuseau, définissez la variable
d'environnement TZ du service server (ex : TZ=Europe/Paris dans
.env, voir docker-compose.yml et
.env.example) — Go/tzdata la respecte nativement (le
paquet tzdata est déjà installé dans l'image finale), aucun rebuild n'est
nécessaire, un simple docker compose up -d --force-recreate server
suffit. Le champ "Prochaine exécution" affiché dans l'UI est, lui, toujours
converti dans le fuseau du navigateur ; une fois TZ réglé côté
serveur sur votre propre fuseau, les deux coïncident.
| Runbooks | Tâches planifiées | |
|---|---|---|
| Qui peut créer/modifier/supprimer | Admin uniquement (toute la section) |
Operator+ (vérifié par hôte, requireHostAccess(..., "operator")) |
| Qui peut exécuter manuellement | Admin (dans le groupe admin-only) |
Operator+ (vérifié par hôte, requireHostAccess(..., "operator")) |
action validée côté serveur ? |
Oui — whitelist stricte par module |
Non — seul module est vérifié dans une liste connue, action est fait confiance |
| Modules disponibles | 6 (docker/apt/systemd/journal/processes/custom) | 7 (les 6 + restic) |
| Peut cibler plusieurs hôtes en un déclenchement | Oui — un runbook entier peut traverser toute la flotte | Non — un hôte par tâche |
| Peut être planifiée (cron) | Non — manuel uniquement | Oui |
Cette asymétrie est un choix documenté, pas un oubli : un runbook peut enchaîner des actions sur plusieurs hôtes différents en un seul déclenchement (surface de casse plus large), d'où le verrouillage admin-only + whitelist stricte. Une tâche planifiée reste bornée à un seul hôte à la fois.
Les trois handlers (Create/Update/DeleteScheduledTask) appellent
requireHostAccess(..., "operator") sur l'hôte ciblé, exactement comme
run — un viewer, y compris en appelant l'API directement sans passer
par le dashboard, ne peut pas créer/modifier/supprimer une tâche
planifiée. Update/Delete résolvent d'abord la tâche pour retrouver son
host_id (:id dans l'URL est l'id de la tâche, pas de l'hôte).
| Symptôme | Cause probable |
|---|---|
| Un runbook s'arrête après une étape en échec sans continuer | Comportement par défaut — cochez continue_on_failure sur cette étape si l'échec ne doit pas bloquer la suite |
Impossible d'ajouter restic comme module dans un runbook |
Non supporté par design — utilisez une tâche planifiée pour un backup Restic récurrent, ou le bouton Lancer un backup de l'onglet Sauvegardes pour un déclenchement ponctuel |
| L'action d'une tâche planifiée semble accepter n'importe quel texte | Normal — seul module est validé côté serveur, action est fait confiance (voir §2.3) ; une faute de frappe échouera silencieusement côté agent, pas côté validation |
| Une tâche "manuelle" apparaît quand même dans un export/API brut avec un cron | C'est la sentinelle 0 0 29 2 * + enabled=false (voir §2.1) — pas un vrai cron actif |
| La "Prochaine exécution" affichée ne correspond pas à l'heure définie dans le cron (ex : décalée de 1-2h) | Le serveur tourne en UTC par défaut — définissez TZ sur votre propre fuseau (voir §2.4) |
Runbook bloqué en running sans jamais passer completed/failed
|
La commande de l'étape en cours n'a jamais atteint un état terminal côté agent (agent déconnecté, commande perdue) — vérifiez les logs de l'étape en cours avant de relancer |
Voir aussi Webhooks Git et suivi de releases pour
l'autre famille de déclencheurs, Sauvegardes Restic pour
le détail du module restic utilisable en tâche planifiée, et la section
Runbooks & Tâches planifiées du
README pour le tableau complet des routes API.
Intégrations
Automatisation
Sauvegardes
Alertes & Monitoring
Compte & Sécurité
Hôtes
Interface