Écrire la marche à suivre : mise en production et montée de version

PUBLICATION.md donne les gestes pas à pas, avec le contrôle attendu à
chaque étape : première mise en production, montée de version (0.1.0 →
0.1.1), retour arrière si la mise à jour échoue, désinstallation.

Deux points qui se paient cher s'ils sont oubliés y sont explicites :
`--version` est obligatoire pour une nouvelle version applicative (sans
lui le script reproduit celle du manifeste), et la sauvegarde de sécurité
pré-upgrade ne contient PAS le répertoire de données.

README et A_FAIRE renvoient au fichier plutôt que de tripler la
procédure. Dernière URL fictive éliminée : gitea.exemple.org subsistait
dans l'exemple CI de publier-release.sh.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
mathieu
2026-08-18 21:05:56 +02:00
co-authored by Claude Opus 5
parent 7ab423783f
commit 54a22b1579
4 changed files with 318 additions and 120 deletions
+52 -117
View File
@@ -1,147 +1,82 @@
# À faire avant la première installation
# État du paquet
État au 2026-08-18. Ce qui est fait est conservé en bas de page : le savoir *pourquoi*
c'était à faire reste utile à la prochaine version.
Mis à jour le 2026-08-18, après une installation, une sauvegarde et une mise à jour
réussies sur le serveur réel.
**Aucune tâche bloquante.** Ce fichier garde les contraintes permanentes et le
journal de ce qui a été réglé — le *pourquoi* resservira à la prochaine version.
---
## 1. Rendre le dépôt du code accessible sans authentification — BLOQUANT
## Publier une nouvelle version
`ynh_setup_source` télécharge l'archive **sans jeton**. Tant que le dépôt `mabibli`
est privé, l'installation échoue au téléchargement.
📖 La marche à suivre est dans [`PUBLICATION.md`](PUBLICATION.md) — première mise en
production, montée de version, retour arrière, désinstallation.
### Le symptôme, et pourquoi il induit en erreur
En résumé : `./build/publier-release.sh --version X.Y.Z`, tag et release sur le dépôt
du code, téléversement de l'archive, puis commit **et push** du manifeste.
Constaté le 2026-08-18, sans authentification :
```
/mathieu/mabibli → 404
/mathieu/mabibli/releases → 404
/api/v1/repos/mathieu/mabibli → 404
```
Gitea répond **404 et non 403** à un visiteur anonyme sur un dépôt privé, pour ne pas
révéler son existence. Le symptôme est donc **exactement le même** que « la release
n'a pas été créée » ou « le fichier n'a pas été téléversé ». Ne pas chercher du côté
de la release avant d'avoir réglé la visibilité : les deux causes sont indiscernables.
Que le dépôt existe bien est vérifiable autrement, par SSH (clé, donc authentifié) :
```
git ls-remote --tags origin
```
### Ce qu'il faut faire
Dans Gitea, sur le dépôt `mathieu/mabibli` : *Settings → Danger Zone → Make
repository public*. Le code est déjà sous AGPL-3.0-or-later, la publication est
cohérente avec la licence.
Si le dépôt doit rester privé, il faut héberger l'archive ailleurs, sur une URL
publique, et faire pointer `--base-url` dessus. Un jeton dans l'URL du manifeste
serait à écarter : le manifeste est lu par YunoHost et lisible sur le serveur.
Le suffixe `~ynhN` se bump à la main quand seul le paquet change (conf, scripts) sans
nouvelle archive — c'est ce qui a été fait pour `~ynh2` et `~ynh3`.
---
## 2. Créer la release et y téléverser l'archive
# Contraintes permanentes — ce ne sont pas des tâches
À faire (ou à vérifier — voir point 1, tant que le dépôt est privé on ne peut pas
savoir si c'est déjà fait).
## Le dépôt du code doit rester public
Le tag est déjà poussé : `v0.1.0``922fd02`. Reste à créer la release
correspondante dans l'interface Gitea et à y téléverser :
```
build/dist/mabibli-0.1.0-linux-x64.tar.gz
```
⚠️ **L'archive à téléverser est celle produite le 2026-08-18**, `sha256`
`e3316bd05cd71234403695bab405f48009d8d6186b0074235396d622c8c0caef`. Une archive plus
ancienne traînant sur le disque ne correspondrait plus au manifeste, et
l'installation s'interromprait à la vérification d'intégrité — comportement voulu,
mais autant ne pas s'y heurter.
⚠️ Elle fait **69 Mo** : c'est normal, le publish est *self-contained* et embarque le
runtime .NET. C'est précisément ce qui évite d'installer `dotnet-runtime` sur le
serveur YunoHost.
### Comment vérifier
```
curl -fsSLI "https://git.akbar.nohost.me/mathieu/mabibli/releases/download/v0.1.0/mabibli-0.1.0-linux-x64.tar.gz" | head -1
```
Doit répondre `HTTP/2 200`, **sans être connecté**. Et le `sha256` du manifeste doit
correspondre à l'archive réellement déposée :
```
sha256sum build/dist/mabibli-0.1.0-linux-x64.tar.gz
grep sha256 manifest.toml
```
---
## 3. Committer et pousser le paquet
Le manifeste corrigé n'est pas encore poussé. `yunohost app install <url du dépôt>`
lit le manifeste **depuis Gitea**, pas depuis la copie locale : sans ce push,
l'installation repartira sur l'ancienne URL fictive.
```
git add -A && git commit && git push
```
---
# Contrainte permanente — ce n'est pas une tâche
`ynh_setup_source` télécharge **sans jeton**. Sur un dépôt privé, Gitea répond
**404 et non 403** à un anonyme : le symptôme est identique à « la release n'existe
pas », ce qui envoie chercher au mauvais endroit. Ne pas mettre de jeton dans l'URL
du manifeste — il serait lisible sur le serveur.
## L'application exige un domaine entier, pas un sous-chemin
**Contrainte technique, pas un choix.** MaBibli doit être installée sur
`mabibli.mondomaine.tld`, et **non** sur `mondomaine.tld/mabibli`.
MaBibli s'installe sur `mabibli.mondomaine.tld`, **pas** sur `mondomaine.tld/mabibli`.
### Pourquoi
Deux éléments sont figés **à la compilation** du client Blazor WebAssembly : la balise
`<base href="/">` de `index.html`, et les empreintes d'intégrité de
`service-worker-assets.js`. Les réécrire sur le serveur casserait le service worker,
donc le mode hors-ligne — et rien n'est recompilé sur le serveur, c'est tout l'intérêt
du self-contained. Le paquet déclare donc l'application en `full_domain`.
Deux éléments sont figés **à la compilation** du client Blazor WebAssembly :
Lever cette contrainte demanderait une archive **par chemin d'installation**, ou une
compilation sur le serveur. Les deux annulent le bénéfice du self-contained.
- la balise `<base href="/">` de `index.html`, qui détermine la racine de toutes les
URL de l'application ;
- les empreintes d'intégrité inscrites dans `service-worker-assets.js`, qui
garantissent que le service worker sert bien les fichiers attendus.
## `install_dir` finit par appartenir à l'application, pas à root
Réécrire ces valeurs sur le serveur au moment de l'installation casserait les
empreintes, donc le service worker, donc le fonctionnement hors-ligne. Et comme
rien n'est recompilé côté serveur — c'est tout l'intérêt du déploiement
self-contained —, il n'existe pas de solution propre pour un sous-chemin.
Le manifeste demande `owner = "root:rwx"` pour que le service ne puisse pas réécrire
ses binaires, mais le helper `_ynh_apply_default_permissions` repasse derrière avec un
`chown -R mabibli:mabibli`. L'intention tient quand même, portée par
`ProtectSystem=strict` dans l'unité systemd : tout est en lecture seule sauf
`ReadWritePaths=`, qui ne liste que le `data_dir`.
Le paquet déclare donc l'application en `full_domain` auprès de YunoHost, qui
demandera un domaine dédié à l'installation.
### Si tu voulais lever cette contrainte plus tard
Il faudrait produire une archive **par chemin d'installation**, ou recompiler sur le
serveur. Les deux annulent le bénéfice du self-contained. À moins d'un besoin réel,
un sous-domaine reste la bonne réponse.
⚠️ Ne pas retirer `ProtectSystem=strict` en croyant que la propriété des fichiers
protège encore.
---
# Fait
## Les deux pièges systemd — 2026-08-18
Découverts à la première installation réelle, chacun a coûté un cycle complet. Ni
l'un ni l'autre ne peut sortir d'un lancement du binaire à la main : ils tiennent au
gestionnaire de services.
| Piège | Symptôme | Correction |
|---|---|---|
| `Environment=` découpe sur les espaces | `ArgumentException … at index 0` | guillemeter toute la ligne |
| `ProtectHome=yes` masque `/home` | `SQLite Error 14: unable to open database file` | `ProtectHome=tmpfs` + `BindPaths=` |
Détail et mesures dans les commentaires de `conf/systemd.service`, à ne pas retirer.
## L'URL de démonstration a été remplacée — 2026-08-18
Le `manifest.toml` portait une URL **fictive** (`gitea.example.org`) : le paquet ne
pouvait pas connaître le vrai domaine Gitea au moment de sa création. Constaté en
conditions réelles — l'installation s'arrête net au `Prefetching asset main`.
Corrigé par `./build/publier-release.sh`, qui recompile, vérifie le publish, produit
l'archive, calcule son `sha256` et l'inscrit dans le manifeste avec la bonne URL.
`https://git.akbar.nohost.me/mathieu/mabibli/releases/download` est désormais la
valeur **par défaut** de `--base-url` dans le script : l'option n'est plus à passer.
Les occurrences hors manifeste, que le script ne touche pas, ont été traitées à la
main : `README.md` et `conf/systemd.service` (directive `Documentation=`). Le
contrôle reste `grep -rn "gitea.example.org" .` — il ne doit plus rien remonter que
ce fichier-ci.
`manifest.toml` portait `gitea.example.org` : l'installation s'arrêtait net au
`Prefetching asset main`. Corrigé partout (`manifest.toml`, `README.md`,
`conf/systemd.service`, et la valeur par défaut de `--base-url`). Contrôle :
`grep -rn "gitea.example.org" .` ne doit plus rien remonter que ce fichier-ci.
## L'archive ne va plus dans git — 2026-08-18