From 34d45d7448a439e6936d3aa4631f15ad627914df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zachary=20Gu=C3=A9not?= Date: Sun, 13 Sep 2026 22:39:22 +0200 Subject: [PATCH] chore(ops): create only the state directories the instance uses Co-Authored-By: Claude Opus 5 --- ops/assemble-standalone.sh | 66 ++++++++++++++++++++++++++++++++++++++ ops/deploy-lxc.sh | 24 +++----------- scripts/run.sh | 24 +++++++++++--- 3 files changed, 91 insertions(+), 23 deletions(-) create mode 100755 ops/assemble-standalone.sh diff --git a/ops/assemble-standalone.sh b/ops/assemble-standalone.sh new file mode 100755 index 000000000..c50cc6f4b --- /dev/null +++ b/ops/assemble-standalone.sh @@ -0,0 +1,66 @@ +#!/usr/bin/env bash +# +# Assemble l'arborescence d'exécution à partir d'un dépôt déjà construit. +# +# Le dépôt et l'instance qui tourne n'ont PAS la même forme : le clone contient +# des sources et un `apps/nextjs/.next/standalone` ; l'instance attend +# `apps/nextjs/server.js`, `db/migrations/`, `build/better_sqlite3.node` à sa +# racine. Ce script fait la conversion — les mêmes COPY que le stage `runner` +# du Dockerfile officiel, d'où vient la disposition de /opt/homarr. +# +# Usage : ops/assemble-standalone.sh +# +# Construire d'abord : +# pnpm turbo build --filter=@homarr/nextjs... --filter=@homarr/cli +# +set -euo pipefail + +DEST="${1:?usage: ops/assemble-standalone.sh }" +REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" + +cd "$REPO" + +[ -d apps/nextjs/.next/standalone ] || { + echo "apps/nextjs/.next/standalone absent — construis d'abord :" >&2 + echo " pnpm turbo build --filter=@homarr/nextjs... --filter=@homarr/cli" >&2 + exit 1 +} + +mkdir -p "$DEST" + +# L'ordre suit le Dockerfile : le standalone d'abord, le reste par-dessus. +cp -a apps/nextjs/.next/standalone/. "$DEST/" +mkdir -p "$DEST/apps/nextjs/.next" +cp -a apps/nextjs/.next/static "$DEST/apps/nextjs/.next/static" +cp -a apps/nextjs/public "$DEST/apps/nextjs/public" +cp -a apps/nextjs/next.config.ts apps/nextjs/package.json pnpm-workspace.yaml "$DEST/" + +mkdir -p "$DEST/apps/cli" +cp -a packages/cli/cli.cjs "$DEST/apps/cli/cli.cjs" + +# Binaire natif : lié à l'architecture et à l'ABI Node de la machine qui a +# construit. Assembler et exécuter sur la même machine rend la question sans +# objet ; c'est le déploiement à distance qui doit la poser. +mkdir -p "$DEST/build" +cp -a node_modules/better-sqlite3/build/Release/better_sqlite3.node "$DEST/build/" + +mkdir -p "$DEST/db" +rm -rf "$DEST/db/migrations" +cp -a packages/db/migrations "$DEST/db/migrations" + +# run.sh n'est copié que s'il manque, jamais écrasé. Sur le LXC, l'installateur +# a adapté le sien — il annonce le port 80 là où celui du dépôt annonce 7575 — +# et l'écraser ferait écouter nginx sur deux ports différents selon la famille +# d'adresses. Même raison pour entrypoint.sh, nginx.conf et redis.conf, qui +# appartiennent à l'installation et ne sont pas copiés du tout. +if [ -f "$DEST/run.sh" ]; then + echo "run.sh déjà présent — laissé tel quel (il peut être adapté à cette installation)." + if ! diff -q scripts/run.sh "$DEST/run.sh" > /dev/null; then + echo " il diffère de scripts/run.sh : \`diff scripts/run.sh $DEST/run.sh\` pour voir quoi." + fi +else + cp -a scripts/run.sh "$DEST/run.sh" + chmod +x "$DEST/run.sh" +fi + +echo "Assemblé dans $DEST ($(du -sh "$DEST" | cut -f1))" diff --git a/ops/deploy-lxc.sh b/ops/deploy-lxc.sh index dfaa1d439..2863d03ef 100755 --- a/ops/deploy-lxc.sh +++ b/ops/deploy-lxc.sh @@ -77,25 +77,11 @@ say "Assemblage de l'arborescence à envoyer" STAGE="$(mktemp -d)" trap 'rm -rf "$STAGE"' EXIT -# L'ordre suit le Dockerfile : le standalone d'abord, le reste par-dessus. -cp -a apps/nextjs/.next/standalone/. "$STAGE/" -mkdir -p "$STAGE/apps/nextjs/.next" -cp -a apps/nextjs/.next/static "$STAGE/apps/nextjs/.next/static" -cp -a apps/nextjs/public "$STAGE/apps/nextjs/public" -cp -a apps/nextjs/next.config.ts apps/nextjs/package.json pnpm-workspace.yaml "$STAGE/" - -mkdir -p "$STAGE/apps/cli" -cp -a packages/cli/cli.cjs "$STAGE/apps/cli/cli.cjs" - -# Binaire natif : compilé ici, chargé là-bas. Même architecture et même ABI Node -# (24.x des deux côtés) sont donc des prérequis — le contrôle est plus bas. -mkdir -p "$STAGE/build" -cp -a node_modules/better-sqlite3/build/Release/better_sqlite3.node "$STAGE/build/" - -mkdir -p "$STAGE/db" -cp -a packages/db/migrations "$STAGE/db/migrations" - -echo "Arborescence prête : $(du -sh "$STAGE" | cut -f1)" +# Même assemblage que pour une installation construite sur place : un seul +# endroit décrit la disposition d'exécution, et les deux chemins ne peuvent pas +# diverger. `run.sh` en fait partie, mais il est exclu du rsync plus bas — +# celui de l'installation est adapté à son port. +"$REPO/ops/assemble-standalone.sh" "$STAGE" # --------------------------------------------------------------------------- say "Contrôle de compatibilité du binaire natif" diff --git a/scripts/run.sh b/scripts/run.sh index efcc50f9f..97436c975 100644 --- a/scripts/run.sh +++ b/scripts/run.sh @@ -1,9 +1,25 @@ #!/usr/bin/env bash -# Create sub directories in volume -mkdir -p /appdata/db -mkdir -p /appdata/redis -mkdir -p /appdata/trusted-certificates +# Create the directories this instance will actually write to. +# +# Derived from the configuration rather than hard-coded, so an installation that +# stores its state elsewhere — a bare-metal one under /var/lib, say — does not +# get an empty /appdata recreated behind its back at every start. The defaults +# reproduce the image's layout exactly: the Dockerfile sets DB_URL to +# /appdata/db/db.sqlite and DB_DIALECT to sqlite, and REDIS_IS_EXTERNAL to false. +mkdir -p "${LOCAL_CERTIFICATE_PATH:-/appdata/trusted-certificates}" + +# Only for SQLite: on any other engine DB_URL is a connection string, and its +# dirname would be a meaningless path. +if [ "${DB_DIALECT:-sqlite}" = "sqlite" ]; then + mkdir -p "$(dirname "${DB_URL:-/appdata/db/db.sqlite}")" +fi + +# The bundled Redis reads its directory from redis.conf; creating it when an +# external server is used would leave an empty directory nobody writes to. +if [ "$REDIS_IS_EXTERNAL" != "true" ]; then + mkdir -p /appdata/redis +fi # Run migrations if [ "$DB_MIGRATIONS_DISABLED" = "true" ]; then