chore(ops): move instance state to /var/lib/homarr without touching the image
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
34d45d7448
commit
a029760f66
3 files changed
+119
-20
No files matched your search
@@ -24,6 +24,34 @@ Après déploiement, le contrôle qui compte n'est pas que le nouveau widget
|
||||
s'affiche : c'est que les intégrations **préexistantes** fonctionnent encore.
|
||||
C'est la seule preuve que `SECRET_ENCRYPTION_KEY` n'a pas bougé.
|
||||
|
||||
## Déplacer l'état hors de /appdata
|
||||
|
||||
`/appdata` vient de l'image Docker, où c'est un point de montage. Sur une
|
||||
machine, il ne suit aucune convention : l'état d'un service se range sous
|
||||
`/var/lib`. La correction se fait sur l'**instance installée**, jamais dans le
|
||||
dépôt — ni le code ni le Dockerfile ne sont touchés, sans quoi chaque rebase sur
|
||||
l'amont rouvrirait le sujet.
|
||||
|
||||
```bash
|
||||
sudo ops/use-var-lib-homarr.sh /opt/homarr # ou /opt/homarr-dev
|
||||
```
|
||||
|
||||
Le script réécrit `/appdata` en `/var/lib/homarr` dans le `run.sh` et le
|
||||
`redis.conf` de l'instance, sauvegarde chaque fichier avant de le toucher, et
|
||||
ajoute `LOCAL_CERTIFICATE_PATH` au démarrage. Cette dernière ligne n'est pas
|
||||
cosmétique : le chemin des certificats n'est pas lu par `run.sh` mais par
|
||||
l'application, qui retombe sur le dossier de l'image dès qu'il manque — elle
|
||||
recréerait donc `/appdata` au premier certificat chargé.
|
||||
|
||||
Le script ne déplace **pas** les données ; il imprime les commandes à passer une
|
||||
fois, service arrêté. Sur cette installation, `/appdata` ne contient qu'un
|
||||
fichier : le certificat racine qui valide la console UniFi locale. Le contrôle
|
||||
d'après-déplacement est donc tout trouvé — si le widget UniFi OS répond encore,
|
||||
le certificat a suivi.
|
||||
|
||||
À relancer après chaque assemblage : `ops/assemble-standalone.sh` recopie le
|
||||
`run.sh` du dépôt quand l'instance n'en a pas, et celui-là parle de `/appdata`.
|
||||
|
||||
## Suivre les mises à jour d'Homarr
|
||||
|
||||
Aujourd'hui `origin` pointe sur le dépôt d'Homarr lui-même et **aucune copie
|
||||
|
||||
Executable
+87
@@ -0,0 +1,87 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Fait pointer une instance Homarr installée sur /var/lib/homarr au lieu de
|
||||
# /appdata.
|
||||
#
|
||||
# `/appdata` vient de l'image Docker, où c'est un point de montage. Sur une
|
||||
# machine, il ne suit aucune convention : l'état d'un service se range sous
|
||||
# /var/lib. Ce script agit sur l'INSTANCE INSTALLÉE — son `run.sh`, son
|
||||
# `redis.conf` — et jamais sur le dépôt : ni le code source ni le Dockerfile ne
|
||||
# sont touchés, pour que le fork reste rebasable sur l'amont.
|
||||
#
|
||||
# Idempotent : le relancer ne fait rien de plus.
|
||||
#
|
||||
# Usage : ops/use-var-lib-homarr.sh <répertoire de l'instance>
|
||||
# ex. : sudo ops/use-var-lib-homarr.sh /opt/homarr
|
||||
# sudo ops/use-var-lib-homarr.sh /opt/homarr-dev
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
DIR="${1:?usage: ops/use-var-lib-homarr.sh <dossier-instance>}"
|
||||
STATE="${HOMARR_STATE_DIR:-/var/lib/homarr}"
|
||||
stamp="$(date +%F-%H%M%S)"
|
||||
|
||||
[ -d "$DIR" ] || { echo "$DIR n'existe pas." >&2; exit 1; }
|
||||
[ -f "$DIR/run.sh" ] || { echo "$DIR/run.sh introuvable — est-ce bien une instance assemblée ?" >&2; exit 1; }
|
||||
|
||||
changed=0
|
||||
|
||||
for file in run.sh redis.conf; do
|
||||
target="$DIR/$file"
|
||||
[ -f "$target" ] || continue
|
||||
grep -q '/appdata' "$target" || continue
|
||||
|
||||
cp -a "$target" "$target.bak-$stamp"
|
||||
sed -i "s#/appdata#$STATE#g" "$target"
|
||||
echo "== $file"
|
||||
diff -u "$target.bak-$stamp" "$target" | sed -n '4,$p' || true
|
||||
changed=1
|
||||
done
|
||||
|
||||
# Le chemin des certificats n'est pas lu par run.sh mais par l'application, qui
|
||||
# retombe sur /appdata/trusted-certificates quand la variable est absente.
|
||||
# Réécrire les `mkdir` ne suffit donc pas : sans cette ligne, Homarr créerait à
|
||||
# nouveau /appdata au premier chargement de certificat.
|
||||
if ! grep -q 'LOCAL_CERTIFICATE_PATH' "$DIR/run.sh"; then
|
||||
[ -f "$DIR/run.sh.bak-$stamp" ] || cp -a "$DIR/run.sh" "$DIR/run.sh.bak-$stamp"
|
||||
awk -v value="$STATE/trusted-certificates" '
|
||||
NR == 1 {
|
||||
print
|
||||
print ""
|
||||
print "# Chemin des certificats de confiance. Sans cette ligne, l'\''application"
|
||||
print "# retombe sur le dossier de l'\''image et le recrée au premier certificat lu."
|
||||
print "export LOCAL_CERTIFICATE_PATH=\"${LOCAL_CERTIFICATE_PATH:-" value "}\""
|
||||
next
|
||||
}
|
||||
{ print }
|
||||
' "$DIR/run.sh" > "$DIR/run.sh.new"
|
||||
cat "$DIR/run.sh.new" > "$DIR/run.sh" # préserve les droits et le propriétaire
|
||||
rm -f "$DIR/run.sh.new"
|
||||
echo "== run.sh : LOCAL_CERTIFICATE_PATH ajouté ($STATE/trusted-certificates)"
|
||||
changed=1
|
||||
fi
|
||||
|
||||
if [ "$changed" -eq 0 ]; then
|
||||
echo "Rien à faire : $DIR ne référence déjà plus /appdata."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mkdir -p "$STATE/trusted-certificates"
|
||||
|
||||
cat <<EOF
|
||||
|
||||
Instance $DIR réglée sur $STATE. Sauvegardes : *.bak-$stamp
|
||||
|
||||
Il reste les DONNÉES, que ce script ne déplace pas — c'est à faire une fois,
|
||||
service arrêté, et c'est irréversible sans sauvegarde :
|
||||
|
||||
sudo systemctl stop homarr
|
||||
sudo mv /appdata/trusted-certificates/*.pem $STATE/trusted-certificates/ 2>/dev/null || true
|
||||
sudo find /appdata -type f # doit ne RIEN afficher avant la suite
|
||||
sudo rm -rf /appdata
|
||||
sudo systemctl start homarr
|
||||
|
||||
Le contrôle qui compte ensuite : l'intégration UniFi OS doit toujours répondre.
|
||||
C'est elle qui valide son certificat avec le CA déplacé — si elle fonctionne,
|
||||
le déplacement a réussi.
|
||||
EOF
|
||||
+4
-20
@@ -1,25 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# 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
|
||||
# Create sub directories in volume
|
||||
mkdir -p /appdata/db
|
||||
mkdir -p /appdata/redis
|
||||
mkdir -p /appdata/trusted-certificates
|
||||
|
||||
# Run migrations
|
||||
if [ "$DB_MIGRATIONS_DISABLED" = "true" ]; then
|
||||
|
||||
Reference in new issue
Block a user