diff --git a/docs/installation/one-command.md b/docs/installation/one-command.md index 395f051..e8f58ca 100644 --- a/docs/installation/one-command.md +++ b/docs/installation/one-command.md @@ -43,14 +43,22 @@ LOUIS_PORT=8080 LOUIS_VERSION=v0.2.0 \ ## Mise à jour +Le plus simple — **relancez la commande d'installation** : elle récupère la +dernière image et redémarre, en conservant vos données et vos secrets. + ```bash -cd louis -docker compose -f docker-compose.prod.yml pull -docker compose -f docker-compose.prod.yml up -d +curl -fsSL https://raw.githubusercontent.com/Association-DataRing/Louis/main/scripts/install.sh | bash +``` + +Ou, depuis le dossier d'installation, le script déposé à l'install : + +```bash +cd louis && ./update.sh ``` -Le service `migrate` ré-applique le schéma (idempotent) avant le redémarrage -de l'app — pas d'étape manuelle. +Dans les deux cas, le service `migrate` ré-applique le schéma (idempotent) +avant le redémarrage de l'app — pas d'étape manuelle. Vos données (base, +documents) et vos secrets (`.env`) sont préservés. ## Sauvegarde diff --git a/scripts/install.sh b/scripts/install.sh index 0f9cb65..bedbea2 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -129,13 +129,26 @@ ensure_docker mkdir -p "$LOUIS_DIR" cd "$LOUIS_DIR" -if [ ! -f "$COMPOSE_FILE" ]; then - curl -fsSL "$LOUIS_REPO_RAW/$COMPOSE_FILE" -o "$COMPOSE_FILE" \ - || fail "Téléchargement de $COMPOSE_FILE impossible depuis $LOUIS_REPO_RAW" - ok "$COMPOSE_FILE téléchargé" -else - ok "$COMPOSE_FILE déjà présent (conservé)" -fi +# On récupère TOUJOURS la dernière version du compose (aucun secret dedans) : +# ré-exécuter ce script vaut donc mise à jour complète de la configuration. +curl -fsSL "$LOUIS_REPO_RAW/$COMPOSE_FILE" -o "$COMPOSE_FILE" \ + || fail "Téléchargement de $COMPOSE_FILE impossible depuis $LOUIS_REPO_RAW" +ok "$COMPOSE_FILE à jour" + +# Script de mise à jour pratique déposé dans le dossier d'install : +# l'utilisateur n'a qu'à le lancer (ou ré-exécuter la commande d'install). +cat > update.sh <<'UPD' +#!/usr/bin/env bash +# Met Louis à jour : récupère la dernière image et redémarre. Vos données +# (base, documents) et vos secrets (.env) sont conservés. +set -euo pipefail +cd "$(dirname "$0")" +echo "Mise à jour de Louis…" +docker compose -f docker-compose.prod.yml pull +docker compose -f docker-compose.prod.yml up -d +echo "Louis est à jour." +UPD +chmod +x update.sh # 3. Secrets ────────────────────────────────────────────────────────────────── # ENCRYPTION_KEY chiffre les clés API stockées : la perdre rend les clés @@ -175,7 +188,7 @@ for _ in $(seq 1 60); do echo " Ouvrez http://localhost:$LOUIS_PORT — l'assistant de premier" echo " lancement vous guide : compte administrateur, clé IA, et c'est prêt." echo "" - echo " Mise à jour : cd $LOUIS_DIR && docker compose -f $COMPOSE_FILE pull && docker compose -f $COMPOSE_FILE up -d" + echo " Mettre à jour : relancez cette commande, ou exécutez $LOUIS_DIR/update.sh" echo " Arrêt : cd $LOUIS_DIR && docker compose -f $COMPOSE_FILE down" # Ouvre le navigateur quand l'environnement le permet (best-effort). if command -v open >/dev/null 2>&1; then open "http://localhost:$LOUIS_PORT" || true diff --git a/src/auth/index.ts b/src/auth/index.ts index 5b33d07..6ff27a5 100644 --- a/src/auth/index.ts +++ b/src/auth/index.ts @@ -79,19 +79,27 @@ export async function verifyPasswordStep( return { status: "ok", needsTotp: user.totpEnabled }; } -// En dev on tourne sur http://localhost — donc PAS de cookie Secure -// (sinon le navigateur ne le renvoie pas et l'utilisateur est -// déconnecté à chaque retour de tab). En prod, Auth.js bascule via la -// détection auto (X-Forwarded-Proto: https). -const isProd = process.env.NODE_ENV === "production"; +// Cookies Secure : activés UNIQUEMENT quand l'instance est servie en HTTPS. +// On ne peut PAS se baser sur NODE_ENV : l'image de production tourne aussi +// en http://localhost (install auto-hébergée) ou en HTTP sur un réseau local, +// où un cookie Secure n'est jamais renvoyé par le navigateur (Safari en tête) +// → la session « saute » à chaque navigation et l'utilisateur est renvoyé au +// login. On déduit donc le schéma de l'URL publique déclarée ; défaut = +// non-secure (HTTP). Derrière un reverse proxy TLS, déclarez +// AUTH_URL=https://votre-domaine pour réactiver les cookies Secure. +const publicUrl = + process.env.AUTH_URL ?? + process.env.NEXTAUTH_URL ?? + process.env.NEXT_PUBLIC_APP_URL ?? + ""; +const useSecureCookies = publicUrl.startsWith("https://"); export const { handlers, auth, signIn, signOut } = NextAuth({ // Indispensable en dev et en self-hosting derrière reverse proxy : // sans ça, Auth.js peut rejeter silencieusement des requêtes et // retourner une session null intermittente. trustHost: true, - // Force le cookie non-Secure en dev pour qu'il fonctionne en HTTP. - useSecureCookies: isProd, + useSecureCookies, // Silence les JWTSessionError : c'est l'erreur "no matching decryption // secret" qui survient quand un cookie a été chiffré avec une valeur // précédente d'AUTH_SECRET. Auth.js gère déjà l'erreur (retourne null