feat(cloudpex): site values out of the script, prompted at install into /etc/cloudpex.conf

cloudpex/cloudpex no longer carries the NAS host, share name, SMB user,
mount point or SMB version. It reads /etc/cloudpex.conf (root:root 0600,
KEY=value) line by line, never sources it, and dies with a hint when the
file is missing, incomplete or has a relative mount point.

cloudpex/install.sh prompts for the five values (regex-validated, re-asked
on bad input so the main installer never aborts), shows and keeps an
existing config unless answered n, and skips the config when no terminal
is attached. README (FR) + root README + CLAUDE.md updated.
This commit is contained in:
bastien
2026-09-22 17:34:18 +02:00
parent 872079bafb
commit 4f8bb61458
6 changed files with 144 additions and 39 deletions
+35 -14
View File
@@ -1,9 +1,13 @@
# cloudpex : montage à la demande du partage SMB CloudPex
# cloudpex : montage à la demande d'un partage SMB (NAS)
`cloudpex` monte et démonte le partage SMB `CloudPex` du NAS (`//192.168.1.111/CloudPex`)
sur `/mnt/cloudpex`. Le mot de passe SMB est demandé à chaque montage. Rien n'est
écrit sur disque, rien ne passe en argument (le mot de passe est transmis à
`mount.cifs` par la variable d'environnement `PASSWD`, invisible dans `ps`).
`cloudpex` monte et démonte un partage SMB du NAS sur un point de montage local.
Le mot de passe SMB est demandé à chaque montage. Rien n'est écrit sur disque,
rien ne passe en argument (le mot de passe est transmis à `mount.cifs` par la
variable d'environnement `PASSWD`, invisible dans `ps`).
Les valeurs propres au site (hôte du NAS, nom du partage, utilisateur SMB, point
de montage, version SMB) ne sont pas dans le script. Elles sont demandées à
l'installation et écrites dans `/etc/cloudpex.conf`, lisible par root seulement.
## Pourquoi à la demande, et pas dans fstab
@@ -26,7 +30,7 @@ tes propres processus.
## Usage
```sh
cloudpex # monte (demande le mot de passe de bchanot_smb)
cloudpex # monte (demande le mot de passe SMB)
cloudpex -s # état
cloudpex -u # démonte (alias : -d, dc, disconnect, disable)
cloudpex -h # aide
@@ -45,19 +49,36 @@ Ce que ça fait, à l'identique de cette machine :
| Cible | Détail |
| --- | --- |
| `/usr/local/bin/cloudpex` | copie du script, `root:root`, `0755` |
| `/mnt/cloudpex` | point de montage, créé vide |
| `/etc/cloudpex.conf` | les cinq valeurs du site, demandées au clavier, `root:root`, `0600` |
| point de montage | créé vide (`/mnt/cloudpex` par défaut) |
| `cifs-utils` | installé via `apt-get` seulement si `mount.cifs` manque |
Réexécutable. `../install.sh` l'appelle sur Linux, donc une installation complète
du dépôt suffit. Rien n'est monté à l'installation.
Questions posées (défaut entre crochets) :
## Paramètres
```
Hôte du NAS (IP ou nom) :
Nom du partage SMB :
Utilisateur SMB :
Point de montage [/mnt/cloudpex] :
Version SMB [3.0] :
```
En tête de `cloudpex` : `SHARE`, `MNT`, `SMB_USER`, `SMB_VERS`. Pour changer de NAS
ou de compte, édite ces valeurs puis relance `./cloudpex/install.sh`.
Réexécutable : si `/etc/cloudpex.conf` existe, il est affiché et gardé sauf
réponse `n`. Sans terminal (`curl | bash`), le script est réinstallé mais la
config n'est ni créée ni modifiée. `../install.sh` appelle cet installeur sur
Linux. Rien n'est monté à l'installation.
## Changer de NAS, de partage ou de compte
Relance `./cloudpex/install.sh` et réponds `n` à « La garder ? », ou édite
`/etc/cloudpex.conf` en root (format `CLÉ=valeur`, une par ligne : `HOST`,
`SHARE`, `SMB_USER`, `MNT`, `SMB_VERS`). Le script lit ce fichier ligne à ligne,
il ne l'exécute jamais.
## Dépannage
- `config absente` : lance `./cloudpex/install.sh` depuis un terminal.
- Échec du montage : `dmesg | tail` (mot de passe, réseau, ou version SMB
refusée par le NAS : essayer `SMB_VERS="3.1.1"`).
- Démontage refusé (fichiers ouverts) : `lsof +D /mnt/cloudpex`, fermer, réessayer.
refusée par le NAS : essayer `SMB_VERS=3.1.1` dans la config).
- Démontage refusé (fichiers ouverts) : `lsof +D <point de montage>`, fermer,
réessayer.
+23 -9
View File
@@ -1,18 +1,16 @@
#!/usr/bin/env bash
# cloudpex-mount — monte / démonte le partage SMB CloudPex du NAS
# Usage : cloudpex-mount -> monte (demande le mot de passe)
# cloudpex-mount -u -> démonte
# cloudpex-mount -s -> état
# cloudpex — monte / démonte le partage SMB du NAS déclaré dans /etc/cloudpex.conf
# Usage : cloudpex -> monte (demande le mot de passe)
# cloudpex -u -> démonte
# cloudpex -s -> état
# Aucun credential n'est écrit sur disque ni passé en argument (invisible dans ps).
set -euo pipefail
SHARE="//192.168.1.111/CloudPex"
MNT="/mnt/cloudpex"
SMB_USER="bchanot_smb"
SMB_VERS="3.0"
CONF="/etc/cloudpex.conf"
# Re-lance le script en root si nécessaire (avant toute saisie du mot de passe)
# Re-lance le script en root si nécessaire (avant toute saisie du mot de passe,
# et avant de lire la config, lisible par root seulement)
if [[ $EUID -ne 0 ]]; then
exec sudo -- "$0" "$@"
fi
@@ -23,6 +21,22 @@ OWNER_GID="${SUDO_GID:-1000}"
die() { echo "Erreur : $*" >&2; exit 1; }
# Valeurs propres au site (hôte, partage, utilisateur, point de montage, version),
# écrites par cloudpex/install.sh au format CLÉ=valeur. Lues ligne à ligne,
# jamais sourcées : le fichier de config n'exécute rien.
conf_get() { sed -n "s/^$1=//p" "$CONF" | head -n 1; }
[[ -r $CONF ]] || die "config absente : $CONF (lance cloudpex/install.sh)"
HOST="$(conf_get HOST)"
SHARE_NAME="$(conf_get SHARE)"
SMB_USER="$(conf_get SMB_USER)"
MNT="$(conf_get MNT)"
SMB_VERS="$(conf_get SMB_VERS)"
[[ -n $HOST && -n $SHARE_NAME && -n $SMB_USER && -n $MNT && -n $SMB_VERS ]] \
|| die "config incomplète : $CONF (relance cloudpex/install.sh)"
[[ $MNT == /* ]] || die "MNT doit être un chemin absolu ($CONF)"
SHARE="//${HOST}/${SHARE_NAME}"
is_mounted() { mountpoint -q "$MNT"; }
do_status() {
+73 -13
View File
@@ -1,26 +1,86 @@
#!/usr/bin/env bash
# cloudpex/install.sh — installe la commande `cloudpex` (montage à la demande du
# partage SMB CloudPex du NAS, voir README.md) telle qu'elle est déployée ici :
# /usr/local/bin/cloudpex root:root 0755
# /mnt/cloudpex point de montage (vide tant que rien n'est monté)
# cloudpex/install.sh — installe la commande `cloudpex` (montage à la demande d'un
# partage SMB, voir README.md) telle qu'elle est déployée ici :
# /usr/local/bin/cloudpex le script, root:root 0755
# /etc/cloudpex.conf hôte, partage, utilisateur SMB, point de montage,
# version SMB : demandés ici, root:root 0600
# cifs-utils installé si mount.cifs manque (apt-get)
# Réexécutable : réinstalle en place. Ne monte rien, ne stocke aucun identifiant.
# Réexécutable : réinstalle le script en place et propose de garder la config
# existante. Sans terminal (curl | bash), la config n'est ni créée ni modifiée.
# Ne monte rien, ne stocke aucun mot de passe.
# Usage : ./cloudpex/install.sh (appelé aussi par ../install.sh sur Linux)
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
TARGET=/usr/local/bin/cloudpex
MNT=/mnt/cloudpex
CONF=/etc/cloudpex.conf
die() { echo "Erreur : $*" >&2; exit 1; }
# Saisie validée : ask VAR "libellé" "défaut" "regex autorisée". Redemande tant
# que la valeur ne correspond pas ; la valeur vide prend le défaut.
ask() {
local value
while :; do
read -rp "$2${3:+ [$3]} : " value || die "saisie interrompue"
value="${value:-$3}"
[[ $value =~ ^$4$ ]] && break
echo " valeur invalide, format attendu : $4" >&2
done
printf -v "$1" '%s' "$value"
}
# Demande les cinq valeurs propres au site et les écrit dans $CONF (root, 0600).
# Les formats refusent ce qui casserait la ligne d'options de mount.cifs
# (virgule, espace, guillemet) ; seul le nom de partage admet des espaces.
write_conf() {
local host share user mnt vers tmp
ask host "Hôte du NAS (IP ou nom)" "" '[A-Za-z0-9.-]+'
ask share "Nom du partage SMB" "" '[A-Za-z0-9._ -]+'
ask user "Utilisateur SMB" "" '[A-Za-z0-9._-]+'
ask mnt "Point de montage" "/mnt/cloudpex" '/[A-Za-z0-9._/-]+'
ask vers "Version SMB" "3.0" '[0-9]+(\.[0-9]+)*'
tmp="$(mktemp)"
printf 'HOST=%s\nSHARE=%s\nSMB_USER=%s\nMNT=%s\nSMB_VERS=%s\n' \
"$host" "$share" "$user" "$mnt" "$vers" > "$tmp"
sudo install -m 0600 -o root -g root "$tmp" "$CONF"
rm -f "$tmp"
}
# Config : créée au clavier, ou gardée si elle existe déjà (répondre n pour la
# refaire). Sans terminal, rien n'est demandé.
configure() {
local keep=""
if [ ! -t 0 ]; then
[ -f "$CONF" ] || echo "Pas de terminal : $CONF non créé, relance ./cloudpex/install.sh depuis un terminal" >&2
return 0
fi
if [ -f "$CONF" ]; then
echo "Configuration existante ($CONF) :"
sudo sed 's/^/ /' "$CONF"
read -rp "La garder ? [Y/n] " keep || true
case "$keep" in
[nN]*) write_conf ;;
esac
else
write_conf
fi
}
# Le point de montage déclaré dans la config, créé vide s'il manque.
ensure_mountpoint() {
local mnt
[ -f "$CONF" ] || return 0
mnt="$(sudo sed -n 's/^MNT=//p' "$CONF" | head -n 1)"
[ -n "$mnt" ] && sudo install -d -m 0755 "$mnt"
}
if ! command -v mount.cifs >/dev/null 2>&1; then
if command -v apt-get >/dev/null 2>&1; then
sudo apt-get install -y cifs-utils
else
echo "mount.cifs absent et apt-get introuvable : installe cifs-utils à la main" >&2
exit 1
fi
command -v apt-get >/dev/null 2>&1 || die "mount.cifs absent et apt-get introuvable : installe cifs-utils à la main"
sudo apt-get install -y cifs-utils
fi
sudo install -m 0755 -o root -g root "$SCRIPT_DIR/cloudpex" "$TARGET"
sudo install -d -m 0755 "$MNT"
configure
ensure_mountpoint
echo "cloudpex installé : $TARGET (monter : cloudpex · état : cloudpex -s · démonter : cloudpex -u)"