Posté(e) hier à 09:331 j Hello ! Pour celles et ceux qui utilisent des machines sous Debian ou Ubuntu, je partage un script Bash interactif prêt à l’emploi pour configurer le stockage S3 proposé par Next.Ink aux abonnés.C'est une première version en français, je pense rajouter le support des distributions archlinux-like et rendre certaines choses un peu plus paramétrables ensuite.N'oubliez pas de sauvegarder la clé maître qui vous sera donné, dans un endroit sûr.Objectifs :Monter automatiquement un bucket S3 en local.Chiffrer l’intégralité des données avec gocryptfs.Protéger le mot de passe de chiffrement via GPG (clé locale, mot de passe jamais stocké en clair).Obtenir un point de montage transparent dans /media, utilisable comme un stockage classique.Aucune configuration manuelle complexe.Fonctionnalités principales :Script interactif guidé (clés S3, mot de passe, choix du mode).Gestion claire de deux cas :Première machine : initialisation du chiffrement du bucket (création de gocryptfs.conf).Machines suivantes : montage direct sans réinitialisation.Configuration persistante via /etc/fstab (montage automatique au démarrage).Cache local S3FS configurable (pour éviter les blocages en cas d’espace disque limité).Déchiffrement automatique du mot de passe via un wrapper GPG sécurisé (extpass).Fonction --clean pour un nettoyage complet et interactif (montages, cache, clés, configuration).Le but est d’avoir un stockage S3 chiffré, fiable et totalement transparent, sans avoir à se battre avec la configuration à chaque machine.Le script est conçu pour être reproductible, cohérent entre serveurs, et utilisable aussi bien sur une machine principale que sur des serveurs secondaires. #!/usr/bin/env bash set -euo pipefail ################################################## # PARAMÈTRES ################################################## BUCKET="s3-next-ink" ENDPOINT="https://s3.fr1.next.ink" MOUNT_CLEAR="/media/s3next" MOUNT_CRYPT="/media/s3next_crypt" CACHE_DIR="/var/cache/s3fs" CLEAN_CACHE="/run/s3fs-clean" S3FS_PASS="/root/.passwd-s3fs" GPG_EMAIL="s3next@local" GPG_PASS_GPG="/root/s3next.gocryptfs.pass.gpg" GPG_WRAPPER="/usr/local/bin/gocryptfs-pass.sh" ################################################## # ROOT ################################################## if [ "$(id -u)" -ne 0 ]; then echo "Ce script doit être lancé avec sudo." exit 1 fi ################################################## # OUTILS ################################################## section() { echo echo "==================================================" echo "$1" echo "==================================================" } ask_yn() { local q="$1" local def="$2" local p [ "$def" = "O" ] && p="O/n" || p="o/N" local r read -rp "$q ($p) : " r r="${r:-$def}" [[ "$r" =~ ^[Oo]$ ]] } safe_umount() { local mp="$1" if mountpoint -q "$mp"; then umount "$mp" 2>/dev/null || umount -l "$mp" 2>/dev/null || true fi } fstab_add() { grep -Fq "$1" /etc/fstab || echo "$1" >> /etc/fstab } fstab_remove() { sed -i "\|$1|d" /etc/fstab 2>/dev/null || true } ################################################## # MODE --clean ################################################## if [ "${1:-}" = "--clean" ]; then section "NETTOYAGE COMPLET (IRRÉVERSIBLE POUR LES DONNÉES)" ask_yn "Confirmer le nettoyage des DONNÉES S3 ?" "N" || exit 0 ask_yn "DERNIÈRE CONFIRMATION (IRRÉVERSIBLE) ?" "N" || exit 0 echo "Démontage des points de montage…" safe_umount "$MOUNT_CLEAR" safe_umount "$MOUNT_CRYPT" ################################################ # NETTOYAGE DISTANT (OPTIONNEL) ################################################ mkdir -p "$CLEAN_CACHE" "$MOUNT_CRYPT" chmod 700 "$CLEAN_CACHE" echo "Tentative de montage S3 pour nettoyage…" if s3fs "$BUCKET" "$MOUNT_CRYPT" \ -o passwd_file="$S3FS_PASS" \ -o url="$ENDPOINT" \ -o use_path_request_style \ -o use_cache="$CLEAN_CACHE" \ -o ensure_diskfree=1 \ -o nomultipart \ -o multipart_size=5 \ -o max_dirty_data=50 \ -o nonempty; then rm -rf "$MOUNT_CRYPT"/* || true safe_umount "$MOUNT_CRYPT" fi ################################################ # NETTOYAGE LOCAL ################################################ rm -rf "$CLEAN_CACHE" "$CACHE_DIR" "$MOUNT_CLEAR" "$MOUNT_CRYPT" rm -f "$GPG_PASS_GPG" "$GPG_WRAPPER" ################################################ # SUPPRESSION CLÉ GPG (PROPRE) ################################################ if gpg --list-keys "$GPG_EMAIL" >/dev/null 2>&1; then FPR="$(gpg --list-keys --with-colons "$GPG_EMAIL" | awk -F: '/^fpr:/ {print $10; exit}')" if [ -n "$FPR" ]; then gpg --batch --yes --delete-secret-keys "$FPR" || true gpg --batch --yes --delete-keys "$FPR" || true fi fi ################################################ # FSTAB ################################################ fstab_remove "s3fs#$BUCKET" fstab_remove "$MOUNT_CRYPT $MOUNT_CLEAR" systemctl daemon-reload ################################################ # CLÉS S3 (OPTIONNEL) ################################################ if [ -f "$S3FS_PASS" ]; then if ask_yn "Supprimer les clés S3 locales ?" "N"; then rm -f "$S3FS_PASS" fi fi section "NETTOYAGE TERMINÉ" exit 0 fi ################################################## # MODE NORMAL ################################################## section "INSTALLATION S3 CHIFFRÉ" ask_yn "Continuer ?" "O" || exit 0 for p in s3fs gocryptfs gnupg; do dpkg -s "$p" >/dev/null 2>&1 || apt install -y "$p" done mkdir -p "$MOUNT_CLEAR" "$MOUNT_CRYPT" "$CACHE_DIR" chmod 700 "$CACHE_DIR" ################################################## # MODE (INIT OU NON) ################################################## section "MODE" FIRST_INIT=0 if ask_yn "Première initialisation du bucket (création gocryptfs.conf) ?" "N"; then FIRST_INIT=1 fi ################################################## # CLÉS S3 ################################################## section "CLÉS S3" if [ -f "$S3FS_PASS" ]; then chmod 600 "$S3FS_PASS" ask_yn "Clés S3 déjà présentes. Les remplacer ?" "N" && rm -f "$S3FS_PASS" fi if [ ! -f "$S3FS_PASS" ]; then read -rp "Access Key S3 : " AK read -rsp "Secret Key S3 : " SK echo echo "$AK:$SK" > "$S3FS_PASS" chmod 600 "$S3FS_PASS" fi ################################################## # MONTAGE S3 ################################################## section "MONTAGE S3" fstab_add "s3fs#$BUCKET $MOUNT_CRYPT fuse _netdev,nofail,x-systemd.automount,allow_other,nonempty,passwd_file=$S3FS_PASS,use_path_request_style,use_cache=$CACHE_DIR,ensure_diskfree=64,nomultipart,url=$ENDPOINT 0 0" systemctl daemon-reload mount "$MOUNT_CRYPT" || true mountpoint -q "$MOUNT_CRYPT" || exit 1 ################################################## # GPG ################################################## section "GPG" if ! gpg --list-keys "$GPG_EMAIL" >/dev/null 2>&1; then gpg --batch --generate-key <<EOF Key-Type: RSA Key-Length: 4096 Subkey-Type: RSA Subkey-Length: 4096 Name-Real: s3next Name-Email: $GPG_EMAIL Expire-Date: 0 %no-protection %commit EOF fi ################################################## # MOT DE PASSE GOCRYPTFS ################################################## section "MOT DE PASSE DE CHIFFREMENT" if [ ! -f "$GPG_PASS_GPG" ]; then read -rsp "Mot de passe : " P1; echo read -rsp "Confirmation : " P2; echo [ "$P1" = "$P2" ] || exit 1 ask_yn "As-tu sauvegardé ce mot de passe ?" "N" || exit 0 printf "%s" "$P1" | gpg -r "$GPG_EMAIL" -e -o "$GPG_PASS_GPG" fi ################################################## # WRAPPER (UTILISÉ PAR -extpass) ################################################## cat > "$GPG_WRAPPER" <<EOF #!/usr/bin/env bash set -euo pipefail exec gpg --batch --quiet --decrypt "$GPG_PASS_GPG" EOF chmod 700 "$GPG_WRAPPER" ################################################## # BACKEND GOCRYPTFS ################################################## section "BACKEND GOCRYPTFS" TMP_TEST="/tmp/gocryptfs-test-$$" mkdir -p "$TMP_TEST" if [ -f "$MOUNT_CRYPT/gocryptfs.conf" ]; then gocryptfs -q -extpass "$GPG_WRAPPER" "$MOUNT_CRYPT" "$TMP_TEST" || exit 1 safe_umount "$TMP_TEST" else if [ "$FIRST_INIT" -eq 1 ]; then gocryptfs -init "$MOUNT_CRYPT" < <("$GPG_WRAPPER") else echo "Erreur: gocryptfs.conf absent sur le bucket. Ce serveur n'est pas en mode initialisation." exit 1 fi fi rmdir "$TMP_TEST" 2>/dev/null || true ################################################## # MONTAGE FINAL (FSTAB) ################################################## section "MONTAGE FINAL" GOCRYPTFS_BIN="$(command -v gocryptfs)" fstab_add "$MOUNT_CRYPT $MOUNT_CLEAR fuse.$GOCRYPTFS_BIN _netdev,nofail,x-systemd.automount,allow_other,extpass=$GPG_WRAPPER 0 0" systemctl daemon-reload section "TERMINÉ" echo "Commande finale : sudo mount -a" echo "Point d'accès : $MOUNT_CLEAR"
Posté(e) hier à 10:091 j Auteur Je viens de voir qu'on ne peut pas éditer un topic.... 😒Rapide mise à jour pour correction d'un problème de montage :#!/usr/bin/env bash set -euo pipefail umask 077 ################################################## # PARAMETRES ################################################## BUCKET="s3-next-ink" ENDPOINT="https://s3.fr1.next.ink" MOUNT_CLEAR="/media/s3next" MOUNT_CRYPT="/media/s3next_crypt" # Cache s3fs en tmpfs (RAM) pour eviter "no space left" sur /var CACHE_DIR="/var/cache/s3fs" CACHE_TMPFS_SIZE="256m" # doit etre > 114m dans votre cas # Cache dedie au mode --clean CLEAN_CACHE="/var/cache/s3fs-clean" CLEAN_CACHE_TMPFS_SIZE="256m" S3FS_PASS="/root/.passwd-s3fs" GPG_EMAIL="s3next@local" GPG_PASS_GPG="/root/s3next.gocryptfs.pass.gpg" GPG_WRAPPER="/usr/local/bin/gocryptfs-pass.sh" ################################################## # ROOT ################################################## if [ "$(id -u)" -ne 0 ]; then echo "Ce script doit etre lance avec sudo." exit 1 fi ################################################## # OUTILS ################################################## section() { echo echo "==================================================" echo "$1" echo "==================================================" } ask_yn() { local q="$1" local def="$2" local p [ "$def" = "O" ] && p="O/n" || p="o/N" local r read -rp "$q ($p) : " r r="${r:-$def}" [[ "$r" =~ ^[Oo]$ ]] } safe_umount() { local mp="$1" if mountpoint -q "$mp"; then umount "$mp" 2>/dev/null || umount -l "$mp" 2>/dev/null || true fi } fstab_add() { grep -Fq "$1" /etc/fstab || echo "$1" >> /etc/fstab } fstab_remove_contains() { local needle="$1" sed -i "\|$needle|d" /etc/fstab 2>/dev/null || true } ensure_fuse_allow_other() { if [ -f /etc/fuse.conf ]; then grep -Eq '^\s*user_allow_other\s*$' /etc/fuse.conf || echo "user_allow_other" >> /etc/fuse.conf fi } ensure_dir_mountpoint() { local p="$1" local mode="${2:-755}" # Si un fichier 0 octet existe a la place (effet d'un essai precedent), on le supprime. if [ -e "$p" ] && [ ! -d "$p" ]; then if [ -f "$p" ] && [ ! -s "$p" ]; then rm -f "$p" else echo "Erreur: $p existe et n'est pas un dossier." echo "Corriger: sudo rm -f '$p' ; sudo mkdir -p '$p'" exit 1 fi fi install -d -m "$mode" "$p" } ensure_tmpfs_cache() { local dir="$1" local size="$2" ensure_dir_mountpoint "$dir" 700 if ! mountpoint -q "$dir"; then mount -t tmpfs -o "rw,nosuid,nodev,noexec,mode=700,size=$size" tmpfs "$dir" fi } wipe_dir_contents() { local dir="$1" [ -d "$dir" ] || return 0 find "$dir" -mindepth 1 -maxdepth 1 -exec rm -rf -- {} + 2>/dev/null || true } ################################################## # MODE --clean ################################################## if [ "${1:-}" = "--clean" ]; then section "NETTOYAGE COMPLET (IRREVERSIBLE POUR LES DONNEES)" ask_yn "Confirmer le nettoyage des DONNEES S3 ?" "N" || exit 0 ask_yn "DERNIERE CONFIRMATION (IRREVERSIBLE) ?" "N" || exit 0 echo "Demontage..." safe_umount "$MOUNT_CLEAR" safe_umount "$MOUNT_CRYPT" # Cache tmpfs pour le nettoyage ensure_tmpfs_cache "$CLEAN_CACHE" "$CLEAN_CACHE_TMPFS_SIZE" ensure_dir_mountpoint "$MOUNT_CRYPT" 755 echo "Montage S3 pour nettoyage..." if s3fs "$BUCKET" "$MOUNT_CRYPT" \ -o "passwd_file=$S3FS_PASS" \ -o "url=$ENDPOINT" \ -o "use_path_request_style" \ -o "allow_other" \ -o "nonempty" \ -o "use_cache=$CLEAN_CACHE" \ -o "ensure_diskfree=64" \ -o "nomultipart"; then wipe_dir_contents "$MOUNT_CRYPT" safe_umount "$MOUNT_CRYPT" fi safe_umount "$CLEAN_CACHE" safe_umount "$CACHE_DIR" rm -rf "$CLEAN_CACHE" "$CACHE_DIR" "$MOUNT_CLEAR" "$MOUNT_CRYPT" 2>/dev/null || true rm -f "$GPG_PASS_GPG" "$GPG_WRAPPER" 2>/dev/null || true # Suppression cle GPG if gpg --list-keys "$GPG_EMAIL" >/dev/null 2>&1; then FPR="$(gpg --list-keys --with-colons "$GPG_EMAIL" | awk -F: '/^fpr:/ {print $10; exit}')" if [ -n "$FPR" ]; then gpg --batch --yes --delete-secret-keys "$FPR" || true gpg --batch --yes --delete-keys "$FPR" || true fi fi # FSTAB fstab_remove_contains "s3fs#$BUCKET" fstab_remove_contains "gocryptfs#$MOUNT_CRYPT" fstab_remove_contains "tmpfs $CACHE_DIR" fstab_remove_contains "tmpfs $CLEAN_CACHE" systemctl daemon-reload # Cle S3 locale if [ -f "$S3FS_PASS" ]; then if ask_yn "Supprimer les cles S3 locales ?" "N"; then rm -f "$S3FS_PASS" fi fi section "NETTOYAGE TERMINE" exit 0 fi ################################################## # MODE NORMAL ################################################## section "INSTALLATION S3 CHIFFRE" ask_yn "Continuer ?" "O" || exit 0 section "MODE" FIRST_INIT=0 if ask_yn "Premiere initialisation du bucket (creation gocryptfs.conf) ?" "N"; then FIRST_INIT=1 fi for p in s3fs gocryptfs gnupg fuse3; do dpkg -s "$p" >/dev/null 2>&1 || apt install -y "$p" done ensure_fuse_allow_other ensure_dir_mountpoint "$MOUNT_CLEAR" 755 ensure_dir_mountpoint "$MOUNT_CRYPT" 755 ################################################## # CACHE S3FS (TMPFS) ################################################## section "CACHE S3FS (TMPFS)" ensure_tmpfs_cache "$CACHE_DIR" "$CACHE_TMPFS_SIZE" fstab_remove_contains "tmpfs $CACHE_DIR" fstab_add "tmpfs $CACHE_DIR tmpfs rw,nosuid,nodev,noexec,mode=700,size=$CACHE_TMPFS_SIZE 0 0" ################################################## # CLES S3 ################################################## section "CLES S3" if [ -f "$S3FS_PASS" ]; then chmod 600 "$S3FS_PASS" if ask_yn "Cles S3 deja presentes. Les remplacer ?" "N"; then rm -f "$S3FS_PASS" fi fi if [ ! -f "$S3FS_PASS" ]; then read -rp "Access Key S3 : " AK read -rsp "Secret Key S3 : " SK echo echo "$AK:$SK" > "$S3FS_PASS" chmod 600 "$S3FS_PASS" fi ################################################## # MONTAGE S3 (S3FS) ################################################## section "MONTAGE S3" fstab_remove_contains "s3fs#$BUCKET" fstab_add "s3fs#$BUCKET $MOUNT_CRYPT fuse _netdev,nofail,x-systemd.automount,allow_other,nonempty,passwd_file=$S3FS_PASS,use_path_request_style,use_cache=$CACHE_DIR,ensure_diskfree=64,nomultipart,url=$ENDPOINT,x-systemd.requires-mounts-for=$CACHE_DIR 0 0" systemctl daemon-reload mount "$CACHE_DIR" 2>/dev/null || true mount "$MOUNT_CRYPT" 2>/dev/null || true mountpoint -q "$MOUNT_CRYPT" || { echo "Erreur: montage s3fs echoue sur $MOUNT_CRYPT"; exit 1; } ################################################## # GPG ################################################## section "GPG" if ! gpg --list-keys "$GPG_EMAIL" >/dev/null 2>&1; then gpg --batch --generate-key <<EOF Key-Type: RSA Key-Length: 4096 Subkey-Type: RSA Subkey-Length: 4096 Name-Real: s3next Name-Email: $GPG_EMAIL Expire-Date: 0 %no-protection %commit EOF fi ################################################## # MOT DE PASSE GOCRYPTFS (CHIFFRE VIA GPG) ################################################## section "MOT DE PASSE DE CHIFFREMENT" if [ -f "$GPG_PASS_GPG" ]; then if ask_yn "Mot de passe deja configure. Le remplacer ?" "N"; then rm -f "$GPG_PASS_GPG" fi fi if [ ! -f "$GPG_PASS_GPG" ]; then read -rsp "Mot de passe : " P1; echo read -rsp "Confirmation : " P2; echo [ "$P1" = "$P2" ] || { echo "Erreur: mots de passe differents"; exit 1; } ask_yn "As-tu sauvegarde ce mot de passe ?" "N" || exit 0 printf "%s" "$P1" | gpg -r "$GPG_EMAIL" -e -o "$GPG_PASS_GPG" fi ################################################## # WRAPPER (EXT PASS) ################################################## cat > "$GPG_WRAPPER" <<EOF #!/usr/bin/env bash set -euo pipefail exec gpg --batch --quiet --decrypt "$GPG_PASS_GPG" EOF chmod 700 "$GPG_WRAPPER" ################################################## # GOCRYPTFS CONF (INIT OU VERIF) ################################################## section "BACKEND GOCRYPTFS" if [ -f "$MOUNT_CRYPT/gocryptfs.conf" ]; then if [ "$FIRST_INIT" -eq 1 ]; then echo "Note: gocryptfs.conf deja present. Initialisation ignoree." fi else if [ "$FIRST_INIT" -eq 1 ]; then gocryptfs -init "$MOUNT_CRYPT" < <("$GPG_WRAPPER") else echo "Erreur: gocryptfs.conf absent sur le bucket. Ce serveur n'est pas en mode initialisation." exit 1 fi fi # Test de dechiffrement (evite les surprises au montage final) TMP_TEST="/tmp/gocryptfs-test-$$" ensure_dir_mountpoint "$TMP_TEST" 700 gocryptfs -q -extpass "$GPG_WRAPPER" "$MOUNT_CRYPT" "$TMP_TEST" -o q >/dev/null 2>&1 || { echo "Erreur: mot de passe incorrect (test gocryptfs)"; exit 1; } safe_umount "$TMP_TEST" rmdir "$TMP_TEST" 2>/dev/null || true ################################################## # MONTAGE FINAL (GOCRYPTFS) ################################################## section "MONTAGE FINAL" safe_umount "$MOUNT_CLEAR" ensure_dir_mountpoint "$MOUNT_CLEAR" 755 # Montage immediat (avec -allow_other pour acces utilisateur) gocryptfs -q -allow_other -extpass "$GPG_WRAPPER" "$MOUNT_CRYPT" "$MOUNT_CLEAR" -o q mountpoint -q "$MOUNT_CLEAR" || { echo "Erreur: montage gocryptfs echoue sur $MOUNT_CLEAR"; exit 1; } # Donner acces a l'utilisateur qui a lance sudo DATA_USER="${SUDO_USER:-root}" if [ "$DATA_USER" != "root" ]; then chown "$DATA_USER:$DATA_USER" "$MOUNT_CLEAR" 2>/dev/null || true chmod 775 "$MOUNT_CLEAR" 2>/dev/null || true fi # FSTAB gocryptfs (options gocryptfs via -o, compatibles mount/fstab) fstab_remove_contains "gocryptfs#$MOUNT_CRYPT" fstab_add "gocryptfs#$MOUNT_CRYPT $MOUNT_CLEAR fuse _netdev,nofail,x-systemd.automount,allow_other,extpass=$GPG_WRAPPER,q,x-systemd.requires-mounts-for=$MOUNT_CRYPT 0 0" systemctl daemon-reload section "TERMINE" echo "Ecrire ici: $MOUNT_CLEAR" echo "Backend chiffre (ne pas ecrire): $MOUNT_CRYPT" echo "Commande utile: sudo mount -a"
Posté(e) hier à 11:321 j Auteur Pour finalement m'apercevoir que partager un S3 entre plusieurs machines, c'est une galère monstrueuse.Troisième essai, cette fois ça part plutôt sur un montage sur serveur, et d'autres machines récupéreront cet accès via sshfs. :#!/usr/bin/env bash set -euo pipefail umask 077 ################################################## # PARAMETRES ################################################## BUCKET="s3-next-ink" ENDPOINT="https://s3.fr1.next.ink" MOUNT_CLEAR="/media/s3next" MOUNT_CRYPT="/media/s3next_crypt" CACHE_DIR="/var/cache/s3fs" CACHE_TMPFS_SIZE="512m" CLEAN_CACHE="/var/cache/s3fs-clean" CLEAN_CACHE_TMPFS_SIZE="512m" S3FS_PASS="/root/.passwd-s3fs" GPG_EMAIL="s3next@local" GPG_PASS_GPG="/root/s3next.gocryptfs.pass.gpg" GPG_WRAPPER="/usr/local/bin/gocryptfs-pass.sh" SYSTEMD_SERVICE="/etc/systemd/system/s3next-gocryptfs.service" # Empreinte locale pour detecter tout changement de config distante CONF_FINGERPRINT_FILE="/root/s3next.gocryptfs.fingerprint" ################################################## # ROOT ################################################## if [ "$(id -u)" -ne 0 ]; then echo "Erreur: ce script doit etre lance avec sudo." exit 1 fi ################################################## # OUTILS ################################################## section() { echo echo "==================================================" echo "$1" echo "==================================================" } ask_yn() { local q="$1" local def="$2" local p [ "$def" = "O" ] && p="O/n" || p="o/N" local r read -rp "$q ($p) : " r r="${r:-$def}" [[ "$r" =~ ^[Oo]$ ]] } safe_umount() { local mp="$1" if mountpoint -q "$mp"; then umount "$mp" 2>/dev/null || umount -l "$mp" 2>/dev/null || true fi } fstab_remove_contains() { local needle="$1" sed -i "\|$needle|d" /etc/fstab 2>/dev/null || true } fstab_add() { grep -Fq "$1" /etc/fstab || echo "$1" >> /etc/fstab } ensure_fuse_allow_other() { if [ -f /etc/fuse.conf ]; then grep -Eq '^\s*user_allow_other\s*$' /etc/fuse.conf || echo "user_allow_other" >> /etc/fuse.conf fi } ensure_dir_mountpoint() { local p="$1" local mode="${2:-755}" if [ -e "$p" ] && [ ! -d "$p" ]; then if [ -f "$p" ] && [ ! -s "$p" ]; then rm -f "$p" else echo "Erreur: $p existe et n'est pas un dossier." exit 1 fi fi install -d -m "$mode" "$p" } ensure_tmpfs_cache() { local dir="$1" local size="$2" ensure_dir_mountpoint "$dir" 700 if ! mountpoint -q "$dir"; then mount -t tmpfs -o "rw,nosuid,nodev,noexec,mode=700,size=$size" tmpfs "$dir" fi local avail avail="$(df -Pm "$dir" | awk 'NR==2 {print $4}')" if [ -z "$avail" ] || [ "$avail" -lt 256 ]; then echo "Erreur: cache tmpfs insuffisant sur $dir (disponible: ${avail:-0} MiB)." exit 1 fi } is_s3fs_mount() { local mp="$1" mountpoint -q "$mp" || return 1 local fstype src fstype="$(findmnt -n -o FSTYPE --target "$mp" 2>/dev/null || true)" src="$(findmnt -n -o SOURCE --target "$mp" 2>/dev/null || true)" [[ "$fstype" == "fuse.s3fs" ]] && return 0 [[ "$src" == "s3fs#${BUCKET}"* ]] && return 0 grep -F " $mp " /proc/mounts | grep -qi "s3fs" && return 0 return 1 } install_packages() { export DEBIAN_FRONTEND=noninteractive apt-get update -y >/dev/null 2>&1 || true apt-get install -y gnupg gocryptfs fuse3 >/dev/null apt-get install -y s3fs >/dev/null 2>&1 || apt-get install -y s3fs-fuse >/dev/null } get_clear_owner() { if [ -n "${SUDO_USER:-}" ] && [ "$SUDO_USER" != "root" ]; then echo "$SUDO_USER" else echo "root" fi } fingerprint_remote_conf() { # Requiert un montage s3fs OK sur $MOUNT_CRYPT [ -f "$MOUNT_CRYPT/gocryptfs.conf" ] || return 1 [ -f "$MOUNT_CRYPT/gocryptfs.diriv" ] || return 1 sha256sum "$MOUNT_CRYPT/gocryptfs.conf" "$MOUNT_CRYPT/gocryptfs.diriv" | sha256sum | awk '{print $1}' } verify_or_store_fingerprint() { local fp fp="$(fingerprint_remote_conf)" || { echo "Erreur: empreinte config gocryptfs introuvable."; exit 1; } if [ -f "$CONF_FINGERPRINT_FILE" ]; then local old old="$(cat "$CONF_FINGERPRINT_FILE" 2>/dev/null || true)" if [ -n "$old" ] && [ "$old" != "$fp" ]; then echo "Erreur: gocryptfs.conf/diriv a change sur le bucket (empreinte differente)." echo "Refus de continuer pour eviter de casser un serveur deja en prod." exit 1 fi else echo "$fp" > "$CONF_FINGERPRINT_FILE" chmod 600 "$CONF_FINGERPRINT_FILE" fi } update_fingerprint_after_init() { local fp fp="$(fingerprint_remote_conf)" || return 0 echo "$fp" > "$CONF_FINGERPRINT_FILE" chmod 600 "$CONF_FINGERPRINT_FILE" } ################################################## # MODE --clean ################################################## if [ "${1:-}" = "--clean" ]; then section "NETTOYAGE COMPLET (IRREVERSIBLE POUR LES DONNEES)" ask_yn "Confirmer le nettoyage des DONNEES S3 ?" "N" || exit 0 ask_yn "DERNIERE CONFIRMATION (IRREVERSIBLE) ?" "N" || exit 0 echo "Arret du service gocryptfs si present..." systemctl stop s3next-gocryptfs.service 2>/dev/null || true systemctl disable s3next-gocryptfs.service 2>/dev/null || true rm -f "$SYSTEMD_SERVICE" 2>/dev/null || true systemctl daemon-reload echo "Demontage..." safe_umount "$MOUNT_CLEAR" safe_umount "$MOUNT_CRYPT" safe_umount "$CACHE_DIR" safe_umount "$CLEAN_CACHE" install_packages ensure_fuse_allow_other ensure_tmpfs_cache "$CLEAN_CACHE" "$CLEAN_CACHE_TMPFS_SIZE" ensure_dir_mountpoint "$MOUNT_CRYPT" 755 echo "Montage S3 pour nettoyage..." s3fs "$BUCKET" "$MOUNT_CRYPT" \ -o "passwd_file=$S3FS_PASS" \ -o "url=$ENDPOINT" \ -o "use_path_request_style" \ -o "allow_other" \ -o "nonempty" \ -o "use_cache=$CLEAN_CACHE" \ -o "ensure_diskfree=64" \ -o "nomultipart" if ! is_s3fs_mount "$MOUNT_CRYPT"; then echo "Erreur: $MOUNT_CRYPT ne semble pas etre un montage s3fs, refus de supprimer." safe_umount "$MOUNT_CRYPT" exit 1 fi # Supprime tout le contenu du bucket via s3fs (y compris gocryptfs.conf) find "$MOUNT_CRYPT" -mindepth 1 -maxdepth 1 -exec rm -rf -- {} + 2>/dev/null || true safe_umount "$MOUNT_CRYPT" safe_umount "$CLEAN_CACHE" safe_umount "$CACHE_DIR" rm -rf "$CLEAN_CACHE" "$CACHE_DIR" "$MOUNT_CLEAR" "$MOUNT_CRYPT" 2>/dev/null || true rm -f "$GPG_PASS_GPG" "$GPG_WRAPPER" "$CONF_FINGERPRINT_FILE" 2>/dev/null || true if gpg --list-keys "$GPG_EMAIL" >/dev/null 2>&1; then FPR="$(gpg --list-keys --with-colons "$GPG_EMAIL" | awk -F: '/^fpr:/ {print $10; exit}')" if [ -n "$FPR" ]; then gpg --batch --yes --delete-secret-keys "$FPR" >/dev/null 2>&1 || true gpg --batch --yes --delete-keys "$FPR" >/dev/null 2>&1 || true fi fi fstab_remove_contains "tmpfs $CACHE_DIR" fstab_remove_contains "tmpfs $CLEAN_CACHE" fstab_remove_contains "s3fs#${BUCKET}" systemctl daemon-reload if [ -f "$S3FS_PASS" ]; then if ask_yn "Supprimer les cles S3 locales ?" "N"; then rm -f "$S3FS_PASS" fi fi section "NETTOYAGE TERMINE" exit 0 fi ################################################## # MODE NORMAL ################################################## section "INSTALLATION S3 CHIFFRE" ask_yn "Continuer ?" "O" || exit 0 section "MODE" FIRST_INIT=0 if ask_yn "Premiere initialisation du bucket (creation gocryptfs.conf) ?" "N"; then FIRST_INIT=1 fi ROLE_RW=0 if ask_yn "Cette machine doit pouvoir ECRIRE dans le bucket ?" "N"; then ROLE_RW=1 fi if [ "$FIRST_INIT" -eq 1 ] && [ "$ROLE_RW" -ne 1 ]; then echo "Erreur: l'initialisation exige une machine en ecriture." exit 1 fi install_packages ensure_fuse_allow_other ensure_dir_mountpoint "$MOUNT_CLEAR" 755 ensure_dir_mountpoint "$MOUNT_CRYPT" 755 ################################################## # CACHE S3FS (TMPFS) ################################################## section "CACHE S3FS (TMPFS)" ensure_tmpfs_cache "$CACHE_DIR" "$CACHE_TMPFS_SIZE" fstab_remove_contains "tmpfs $CACHE_DIR" fstab_add "tmpfs $CACHE_DIR tmpfs rw,nosuid,nodev,noexec,mode=700,size=$CACHE_TMPFS_SIZE 0 0" ################################################## # CLES S3 ################################################## section "CLES S3" if [ -f "$S3FS_PASS" ]; then chmod 600 "$S3FS_PASS" if ask_yn "Cles S3 deja presentes. Les remplacer ?" "N"; then rm -f "$S3FS_PASS" fi fi if [ ! -f "$S3FS_PASS" ]; then read -rp "Access Key S3 : " AK read -rsp "Secret Key S3 : " SK echo printf "%s:%s" "$AK" "$SK" > "$S3FS_PASS" chmod 600 "$S3FS_PASS" fi ################################################## # MONTAGE S3 (S3FS) ################################################## section "MONTAGE S3" fstab_remove_contains "s3fs#${BUCKET}" S3FS_RO_OPT="" if [ "$ROLE_RW" -ne 1 ]; then S3FS_RO_OPT=",ro" fi fstab_add "s3fs#${BUCKET} $MOUNT_CRYPT fuse _netdev,nofail,x-systemd.requires=network-online.target,x-systemd.after=network-online.target,allow_other,nonempty,passwd_file=$S3FS_PASS,use_path_request_style,use_cache=$CACHE_DIR,ensure_diskfree=64,nomultipart,url=$ENDPOINT${S3FS_RO_OPT} 0 0" systemctl daemon-reload mount "$CACHE_DIR" >/dev/null 2>&1 || true safe_umount "$MOUNT_CLEAR" safe_umount "$MOUNT_CRYPT" mount "$MOUNT_CRYPT" || { echo "Erreur: montage s3fs echoue sur $MOUNT_CRYPT"; exit 1; } is_s3fs_mount "$MOUNT_CRYPT" || { echo "Erreur: $MOUNT_CRYPT n'est pas un montage s3fs attendu"; exit 1; } ls -la "$MOUNT_CRYPT" >/dev/null 2>&1 || { echo "Erreur: acces au montage s3fs impossible (E/S)"; exit 1; } ################################################## # GPG ################################################## section "GPG" if ! gpg --list-keys "$GPG_EMAIL" >/dev/null 2>&1; then gpg --batch --generate-key <<EOF Key-Type: RSA Key-Length: 4096 Subkey-Type: RSA Subkey-Length: 4096 Name-Real: s3next Name-Email: $GPG_EMAIL Expire-Date: 0 %no-protection %commit EOF fi ################################################## # MOT DE PASSE GOCRYPTFS (CHIFFRE VIA GPG) ################################################## section "MOT DE PASSE DE CHIFFREMENT" if [ ! -f "$GPG_PASS_GPG" ]; then read -rsp "Mot de passe : " P1; echo read -rsp "Confirmation : " P2; echo [ "$P1" = "$P2" ] || { echo "Erreur: mots de passe differents"; exit 1; } ask_yn "As-tu sauvegarde ce mot de passe ?" "N" || exit 0 printf "%s" "$P1" | gpg --batch -r "$GPG_EMAIL" -e -o "$GPG_PASS_GPG" fi cat > "$GPG_WRAPPER" <<EOF #!/usr/bin/env bash set -euo pipefail exec gpg --batch --quiet --decrypt "$GPG_PASS_GPG" EOF chmod 700 "$GPG_WRAPPER" ################################################## # GOCRYPTFS CONF (INIT OU VERIF) ################################################## section "BACKEND GOCRYPTFS" if [ -f "$MOUNT_CRYPT/gocryptfs.conf" ]; then if [ "$FIRST_INIT" -eq 1 ]; then echo "Note: gocryptfs.conf deja present. Initialisation ignoree." fi else if [ "$FIRST_INIT" -eq 1 ]; then gocryptfs -init "$MOUNT_CRYPT" < <("$GPG_WRAPPER") update_fingerprint_after_init else echo "Erreur: gocryptfs.conf absent sur le bucket. Ce serveur n'est pas en mode initialisation." exit 1 fi fi # Verif empreinte distante pour eviter qu'un autre serveur ait reinitialise/cree une autre config verify_or_store_fingerprint ################################################## # SERVICE SYSTEMD (GOCRYPTFS) ################################################## section "MONTAGE FINAL" CLEAR_OWNER="$(get_clear_owner)" # Stop service existant systemctl stop s3next-gocryptfs.service 2>/dev/null || true safe_umount "$MOUNT_CLEAR" ensure_dir_mountpoint "$MOUNT_CLEAR" 755 GOCRYPTFS_RO_FLAG="" if [ "$ROLE_RW" -ne 1 ]; then GOCRYPTFS_RO_FLAG="-ro" fi cat > "$SYSTEMD_SERVICE" <<EOF [Unit] Description=Next.Ink S3 - Montage dechiffre via gocryptfs Wants=network-online.target After=network-online.target media-s3next_crypt.mount Requires=media-s3next_crypt.mount [Service] Type=simple ExecStartPre=-/bin/umount -l $MOUNT_CLEAR ExecStartPre=/bin/mkdir -p $MOUNT_CLEAR ExecStart=/usr/bin/gocryptfs -f -q -allow_other $GOCRYPTFS_RO_FLAG -extpass $GPG_WRAPPER $MOUNT_CRYPT $MOUNT_CLEAR ExecStartPost=/bin/chown $CLEAR_OWNER:$CLEAR_OWNER $MOUNT_CLEAR ExecStartPost=/bin/chmod 775 $MOUNT_CLEAR ExecStop=/bin/umount -l $MOUNT_CLEAR Restart=on-failure RestartSec=2 KillMode=process [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable --now s3next-gocryptfs.service for i in {1..20}; do mountpoint -q "$MOUNT_CLEAR" && break sleep 1 done mountpoint -q "$MOUNT_CLEAR" || { echo "Erreur: montage gocryptfs non actif sur $MOUNT_CLEAR"; systemctl status --no-pager -l s3next-gocryptfs.service || true; exit 1; } section "TERMINE" echo "Ecrire ici: $MOUNT_CLEAR" echo "Backend chiffre (ne pas ecrire): $MOUNT_CRYPT" if [ "$ROLE_RW" -eq 1 ]; then echo "Mode: ECRITURE" else echo "Mode: LECTURE SEULE" fi echo "Service: sudo systemctl status s3next-gocryptfs.service" Modifié hier à 11:331 j par bingo.crepuscule
Posté(e) il y a 23 heures23 h Merci pour ce script!Et en bash, ça change des "scripts" python qu'on nous pond partout.Plusieurs remarques rapides:Utilise plutôt un "Spoiler" (divulgâcheur) ce sera mieux pour le scrollSpoiler...Il y a 3 heures, bingo.crepuscule a dit :Je viens de voir qu'on ne peut pas éditer un topic.... 😒Si (mais alors est-ce un privilège de vénérable?):Ma captureIl y a 2 heures, bingo.crepuscule a dit : Pour finalement m'apercevoir que partager un S3 entre plusieurs machines, c'est une galère monstrueuse.Peux-tu préciser les problèmes que tu rencontres? (même si je pense en connaître certains: le partage entre plusieurs ordis, c'est forcément complexe, mais avec des technos "déconnectées", c'est terrible)Question un peu noob: comment fais-tu pour pallier au problème classique sous Unix du montage échoué: si mon montage échoue, mais que mon logiciel écrit dans mon point de montage, cela ne déclenche pas d'erreur...J'ai ce problème avec mes sauvegardes (mon lecteur USB se monte sur un point précis pour que mes scripts de sauvegarde ne soient pas compliqués), mais si le montage a échoué, mes sauvegardes vont saturer mon disque. Du coup maintenant je change les permissions après montage, mais en cas de panne de courant/arrachement, ça ne change pas le problème.
Posté(e) il y a 20 heures20 h Auteur Malheureusement comme je ne peux pas éditer mes publications, pas possible d'y adjoindre un spoiler ! 😅Concernant le python, c'est à la mode, mais je déteste ça, essentiellement pour des raisons de stabilité. J'ai des vieux scripts bash qui fonctionnent avec des outils standards depuis plus de 15 ans, et je n'ai jamais été em*erdé avec ça, alors que des scripts python obsolètes, cassés pour raison de version, où de changement/disparition de dépendances, c'est une plaie ! 😒 (J'ai conscience de ses qualités, mais à mon sens, je préfère la stabilité)Du coup je m'occupe de tous mes outils en bash, et rien d'autre. Et quand je demande un coup de main à un LLM pour accélérer le boulot, je lui interdit d'utiliser python, ou même npm, la majorité du temps. J'essaie de tout faire le plus possible en bash pour la pérennité. 😄En pratique, les problèmes que j’ai rencontrés viennent surtout du fait que je cherchais à utiliser S3 comme un disque “classique”, alors que ce n’est pas fait pour ça. Dès qu’on sort du cas simple (un seul ordi, peu d’écritures), ça devient vite bancal : lenteurs, comportements bizarres, erreurs difficiles à comprendre, surtout quand on commence à vouloir partager l’accès entre plusieurs machines.Pour ta question sur le montage *nix, je n’ai pas trouvé de solution parfaite non plus. Si le montage échoue et que le point de montage redevient un simple dossier, le système ne bloque rien : les écritures partent ailleurs sans prévenir...Avec des montages réseau ou FUSE, et encore plus avec S3 derrière, on empile des couches qui peuvent casser sans signal clair, j'ai eu un énorme problème en utilisant le script sur plusieurs machines à la fois (avec le chiffrement, je précise, c'était beaucoup moins problématique sans), dès qu'une seconde se connectait, j'avais des soucis de lecture/écriture sur la première, et parfois même le montage chiffré apparaissait comme un simple fichier, plus comme un dossier...C'est pour ça que comme compromis, j'ai pensé à SSHFS. Une seule machine se connecte au S3 avec chiffrement, et ensuite d'autres machines devront se connecter via SSH pour monter ledit répertoire, ainsi on ne casse rien. Mais ça implique d'avoir accès audit serveur de partout, donc plutôt à un dédié/vps en ligne, ou chez soi avec les bons ports ouverts dans un conteneur LXC pour cloisonner le tout. 🙂J'ai bien planché dernièrement sur un script interactif de gestion des domaines .onion avec Tor aussi (100% bash), avec quelques améliorations maison (alias, description...), chaque adresse étant associée à un fichier json, et chiffrement automatique et imposé de chaque clé privé, avec gpg, automatisé.SI ça intéresse du monde je pourrais aussi partager ça, j'ai même intégré la génération de compilation/config mini + ce script + empaquetage dans un paquet .deb depuis les sources pour un paquet minimal préconfiguré "tor-onion" (uniquement pour la publication de domaine)... Et la génération en masse/association à un/des ports spécifiques. 👌Bon par contre, ça risque d'avoir du mal à passer, directement sur le forum, ça représente, avec l'aide integrée et l'anglais + français, autour de 8000 lignes, il me semble 😅Un de ces jours, il va vraiment falloir que j'apprenne à utiliser GIT... Modifié il y a 20 heures20 h par bingo.crepuscule
Rejoindre la conversation
Vous pouvez publier maintenant et vous inscrire plus tard. Si vous avez un compte, connectez-vous maintenant pour publier avec votre compte.