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:
@@ -41,3 +41,12 @@ Root cause: /tmp is tmpfs (50% RAM) → agents fill it → RAM halved + ENOSPC b
|
||||
- [x] README.md steps 12-14 + table rows; CLAUDE.md layout
|
||||
- [x] shellcheck + bash -n (install.sh, cloudpex/install.sh); stub-sudo dry run of the offers
|
||||
- [x] commit on feature branch (no gitea-deploy/, no .githooks changes)
|
||||
|
||||
## Round 2 — cloudpex config out of script, reconcile main/develop, capitalize, merge (2026-09-22)
|
||||
- [x] cloudpex/cloudpex: constants → /etc/cloudpex.conf parsed line by line (never sourced), die if missing
|
||||
- [x] cloudpex/install.sh: prompt host/share/user/mnt/vers (regex-validated), keep-existing [Y/n], no-TTY skip
|
||||
- [x] cloudpex/README.md + README.md + CLAUDE.md: no site values, describe prompts + conf file
|
||||
- [x] registries: BDR-010/011/012, LRN-009/010/011, BLK-005/006, EVAL-002, journal
|
||||
- [ ] reconcile: merge main (a210d01 dtach) into develop via lib helper
|
||||
- [ ] gitflow finish feature → develop (explicit user signal: "puis merge")
|
||||
- [ ] runbook for live apply on this machine
|
||||
|
||||
@@ -26,7 +26,8 @@ etc/profile.d/disk-usage-warning.sh login-time low-disk warning → /etc/pro
|
||||
etc/tmpfiles.d/tmp.conf disk-backed /tmp cleanup rules (offer: /tmp on disk)
|
||||
etc/systemd/ssh.service.d/override.conf sshd OOM-exempt drop-in (offer: SSH memory guard)
|
||||
etc/default/earlyoom earlyoom args, spare sshd / kill node first (same offer)
|
||||
cloudpex/{cloudpex,install.sh,README.md} on-demand CloudPex SMB mount helper → /usr/local/bin (FR docs)
|
||||
cloudpex/{cloudpex,install.sh,README.md} on-demand SMB mount helper → /usr/local/bin; site values
|
||||
prompted at install → /etc/cloudpex.conf, never in the script (FR docs)
|
||||
.claude/{tasks,memory,audits}/ Claude working state
|
||||
```
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ curl -fsSL https://git.bchanot.fr/bchanot/config/raw/branch/master/remote-instal
|
||||
| Path | Purpose |
|
||||
| -------------------- | -------------------------------------------------------------- |
|
||||
| `install.sh` | Installs apt packages + Docker + code-server + RDP (gnome-remote-desktop), backs up old config, deploys vim + bashrc (OS-detected), installs CLI scripts, pipx tools, a low-disk login warning and the `cloudpex` NAS mount helper; ends by offering two system changes (`/tmp` on disk, SSH memory guard). |
|
||||
| `cloudpex/` | On-demand SMB mount of the CloudPex NAS share (`cloudpex` command + its installer). French README inside. |
|
||||
| `cloudpex/` | On-demand SMB mount of a NAS share (`cloudpex` command + its installer). Site values (host, share, SMB user, mount point, SMB version) are prompted at install and stored in `/etc/cloudpex.conf`, never in the script. French README inside. |
|
||||
| `etc/tmpfiles.d/tmp.conf` | Cleanup rules for a disk-backed `/tmp` (wiped at boot, 10-day purge). Deployed by the `/tmp` on disk offer. |
|
||||
| `etc/systemd/ssh.service.d/override.conf` | `ssh.service` drop-in: sshd exempt from the OOM killer + memory reclaim protection. Deployed by the SSH memory guard offer. |
|
||||
| `etc/default/earlyoom` | earlyoom arguments: spare sshd/systemd, kill node/java first. Deployed by the SSH memory guard offer. |
|
||||
@@ -65,7 +65,7 @@ What it does:
|
||||
9. On Linux, installs `etc/profile.d/disk-usage-warning.sh` to `/etc/profile.d/` (needs `sudo`) so each login warns when `/` or `/home` cross 85% usage.
|
||||
10. On Linux, installs **code-server** (VS Code in the browser) via its vendor script — skipped if already present — and enables the `code-server@$USER` systemd service.
|
||||
11. On Linux, sets up **RDP remote login** via `gnome-remote-desktop` (Wayland-native): installs the daemon + `openssl`, generates a self-signed TLS cert once, and prompts interactively for shared "gate" credentials (skipped when no terminal is attached, or already set). Disables `xrdp` if present; opens UFW port `3389` only when UFW is already active.
|
||||
12. On Linux, installs the **`cloudpex`** NAS mount helper to `/usr/local/bin` via `cloudpex/install.sh` (nothing is mounted, no credential stored, see [`cloudpex/README.md`](cloudpex/README.md)).
|
||||
12. On Linux, installs the **`cloudpex`** NAS mount helper to `/usr/local/bin` via `cloudpex/install.sh`, which prompts for the NAS host, share name, SMB user, mount point and SMB version and writes them to `/etc/cloudpex.conf` (root, `0600`; an existing config is shown and kept unless you say `n`; skipped when no terminal is attached). Nothing is mounted, no password stored, see [`cloudpex/README.md`](cloudpex/README.md).
|
||||
13. On Linux, at the very end, **offers** (`[y/N]`, skipped when no terminal is attached) to move **`/tmp` to disk**: Ubuntu mounts `/tmp` as a RAM-backed tmpfs capped at 50% of RAM, which agent runs fill, halving the RAM and breaking every shell with "No space left on device". Accepting masks `tmp.mount` and installs `etc/tmpfiles.d/tmp.conf` (wipe at boot, 10-day purge). Effective at the next reboot.
|
||||
14. On Linux, at the very end, **offers** to keep **SSH reachable under memory pressure**: installs the `ssh.service` drop-in (`OOMScoreAdjust=-1000`, `MemoryMin=256M`) and `earlyoom` with `etc/default/earlyoom` (kills the largest process, `node`/`java` first and never `sshd`, once free RAM and swap both drop under 10%). Restarting `ssh` keeps open sessions. Note: `MemoryMin` protects the sshd daemon only; login sessions live in `user.slice`, so no setting can reserve RAM for a future shell. earlyoom acting in time is the real protection.
|
||||
|
||||
|
||||
+35
-14
@@ -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
@@ -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
@@ -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)"
|
||||
|
||||
Reference in New Issue
Block a user