-
[v0.1b] Script de montage auto+chiffrement du cloud s3 Next.ink pour Linux.
bingo.crepuscule a répondu à un(e) sujet de bingo.crepuscule dans Projets personnels et Gestion communautaireMalheureusement 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...
-
[v0.1b] Script de montage auto+chiffrement du cloud s3 Next.ink pour Linux.
bingo.crepuscule a répondu à un(e) sujet de bingo.crepuscule dans Projets personnels et Gestion communautairePour 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"
-
[v0.1b] Script de montage auto+chiffrement du cloud s3 Next.ink pour Linux.
bingo.crepuscule a répondu à un(e) sujet de bingo.crepuscule dans Projets personnels et Gestion communautaireJe 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"
-
-
[v0.1b] Script de montage auto+chiffrement du cloud s3 Next.ink pour Linux.
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"
-
Deux routeurs OpenWrt ?
bingo.crepuscule a répondu à un(e) sujet de bingo.crepuscule dans Réseaux, Internet, Téléphonie et Services en LigneJ'ai essayé des choses, mais rien à faire, j'ai des équipements accessibles et d'autres pas, depuis le routeur N°1. Parfois c'est aléatoire, et le rasperry N°2 n'est plus accessible... Je ne comprends pas ce qu'il se passe ! 😕
-
Deux routeurs OpenWrt ?
bingo.crepuscule a répondu à un(e) sujet de bingo.crepuscule dans Réseaux, Internet, Téléphonie et Services en LigneLes RPI de ce réseau voient bien les prises connectées et la caméra. 🙂 Les prises connectées autant que la caméra ne sont pas tournées uniquement vers le broadcast, les prises sont sous firmware Tasmota (libre/open source) d'origine, les ayant choisi spécifiquement pour ça, tandis que la camera est une ANNKE NCPT500, prévue aussi bien pour une un fonctionnement autonome, que sur réseau local & cie, et compatible RTSP en sus. 🙂 Je précise que j'ai pu sans problème intégrer tous ces éléments à HomeAssistant que j'utilise également, j'ai le flux de la caméra en direct également via l'intégration générique ou on/off. En pratique, j'essaie actuellement de faire une variante d'un premier montage dont j'avais décrit l'installation ici : https://pepinature.org/fr/gestion_de_l_eau/programmation_avancee_et_automatisation_de_l_irrigation La différence principale tiendra de l'intégration d'asterisk (accès à la ligne fixe en wifi sur le smartphone au jardin/pépinière), de l'abandon de la 4G au profit de la fibre (via le routeur N°1), et d'une solution de secours via un deuxième raspberry Pi4 avec OpenSprinkler qui prendra le relais en cas de problème avec le premier.
-
Deux routeurs OpenWrt ?
bingo.crepuscule a répondu à un(e) sujet de bingo.crepuscule dans Réseaux, Internet, Téléphonie et Services en LigneJ'ai parlé trop vite, j'ai bien désormais accès au routeur N°2, aussi bien via 192.168.1.2 que 192.168.2.1, j'ai accès à deux Raspberry PI connecté en RJ45 au second routeur, depuis le routeur N°1, par contre impossible d'accéder aux prises wifi et camera en RJ45 du routeur N°2, malgré leur présence et attribution de l'IP par ce dernier. Exemple de traceroute : Un des raspberry PI : $ traceroute 192.168.2.115 traceroute to 192.168.2.115 (192.168.2.115), 30 hops max, 60 byte packets 1 _gateway (192.168.1.1) 5.914 ms 6.028 ms * 2 192.168.1.2 (192.168.1.2) 6.228 ms 6.218 ms 6.210 ms 3 192.168.2.115 (192.168.2.115) 7.500 ms 7.492 ms 7.485 ms Une caméra : $ traceroute 192.168.2.130 traceroute to 192.168.2.130 (192.168.2.130), 30 hops max, 60 byte packets 1 _gateway (192.168.1.1) 3.028 ms 3.136 ms * 2 * * * 3 * * * 4 * * * 5 * * * 6 * * * 7 * * * 8 * * * 9 * * * 10 * * * 11 * * * 12 * * * 13 * * * 14 * * * 15 * * * 16 * * * 17 * * * 18 * * * 19 * * * 20 * * * 21 * * * 22 * * * 23 * * * 24 * * * 25 * * * 26 * * * 27 * * * 28 * * * 29 * * * 30 * * *
-
Deux routeurs OpenWrt ?
bingo.crepuscule a répondu à un(e) sujet de bingo.crepuscule dans Réseaux, Internet, Téléphonie et Services en LigneMerci beaucoup, avec cette piste j'ai pu demander à MistralAI comment faire, j'ai enfin accès aux équipements du second routeur depuis le premier désormais 🙂 Je partage le screenshot de la configuration en question si ça peut aider quelqu'un un jour ! 🙂
-
Deux routeurs OpenWrt ?
Bonjour, j'ai acquis récemment deux routeurs (Xiaomi AX 3000T) que j'ai flashé avec OpenWRT dans sa dernière version. Je suis sous Linux depuis environ une quinzaine d'années, donc j'ai quelques bases en matière de desktop/serveur (Ubuntu, Debian, ArchLinux, principalement), mais sur la partie réseau, j'ai des lacunes, je n'arrive pas à accéder à mon second routeur depuis le premier. Dans mon cas de figure voici comment se présente mon réseau : -Le routeur N°1 sous OpenWRT remplace la neufbox, il récupère internet via le boitier PON (fibre optique), branché sur le port Wan, c'est fonctionnel, j'ai même pu récupérer la partie téléphone de SFR via Asterisk et la rediriger vers n'importe quel client SIP sur le réseau. Son adresse IP locale est 192.168.1.1 . -Un répéteur Wifi AC 190 v5 de TP-Link (impossible à flasher avec OpenWRT) récupère la connexion par wifi, pour la répéter, son IP est 192.168.1.101 . -Le routeur N°2 sous OpenWRT récupère la connexion par wifi sur le répéteur, et a une adresse IP statique configurée sur 192.168.1.2 sur sous réseau 255.255.255.0 et passerelle configurée 192.168.1.1. Il offre un accès wifi (deuxième module) et via ethernet aux équipements connectés. Ce routeur a une IP locale (lan / br-lan) de 192.168.2.1 et est configuré sur sous réseau 255.255.255.0 et la passerelle 192.168.1.1. Il alloue des adresses IP à deux Raspberry PI sous Raspberry PI Os connectés dessus en filaire (ethernet), et des prises connectées par wifi sous firmware tasmota. Le problème, c'est que si depuis le routeur N°2 j'accède sans aucun soucis à tous les équipements connectés au routeur N°1, mais l'inverse ne m'est pas possible, je suis dans l'incapacité en étant connecté sur le routeur N°1 à contacter tous les équipements connectés au routeur N°2. Quelqu'un saurait comment régler ça sous Luci ? Petite précision, depuis le premier routeur, je peux joindre le second avec l'adresse IP 192.168.1.2, mais pas avec l'ip 192.168.2.1.
-
Le Linux BAR - Discussion de tout et de rien
Je suis le seul gus du coin à tourner sous Manjaro ? Pour ceux qui ne connaissent pas, c'est une distribution basée sur ArchLinux, disponible sous pas mal d'environnements, et simplifie de beaucoup ArchLinux, sans y perdre en fonctionnalités, elle est aussi accessible que Debian et Ubuntu, de fait, et surtout, c'est du rolling release. Par contre, tous les outils n'étant pas terminés, elle est n'a pas encore atteint officiellement sa première version finale.
-
Votre Dernier Achat
J'dois me gourrer alors ^^
-
Votre Dernier Achat
Ho bordel, comme on se retrouve ! Me souviens que j'étais en 56K sans illimité à l'époque, qu'on discutais, que t'étais au chomdu et tout et toi tu me proposais de me vendre des "jeux" !
-
Votre Dernier Achat
Sp3ud, ton pseudo me dis quelque chose, tu ne tenais pas un site sur la dreamcast dans le début des années 2000 avec un tchat ? Sinon voilà la dernière bête que je viens de trouver 298€ fdpin Chronopost, en promo à -40%, un casque AKG Q701 Quincy Jones noir. C'est le petit frère des K701 et 702, avec câble détachable, et quelques améliorations au niveau du son, sans compter qu'il s'agit d'une série limitée. Niveau son, en gros... Ça poutre ! Dès que j'ai vu la promo, j'ai foncé, car possible de payer en 3 fois sans frais... Chose impossible chez Thomann. :( Bon par contre... Va falloir que je me trouve une très bonne carte son (blindée) pleinement compatible Linux, pour en profiter à fond !
bingo.crepuscule
INpactien
-
Inscription
-
Dernière visite