#!/usr/bin/env bash # # post-install.sh - Personnalisation d'une installation Debian fraîche # # Actions : # - mise à jour du système et installation de curl, wget, git, sudo, locales, # unattended-upgrades (activé) # - création d'un utilisateur sudo et copie des clés SSH de root # - changement du port SSH (via un fichier drop-in) # - fail2ban (optionnel : question posée, ou option -f) avec jail SSH # - alias de confort dans .bashrc (root et utilisateur) # - fuseau horaire et locale # # Usage : sudo ./post-install.sh [-u utilisateur] [-p port_ssh] [-f] [-h] # # Le script est idempotent : il peut être relancé sans dupliquer la config. set -euo pipefail # --- Configuration (surchargeable par variables d'environnement ou options) --- NEW_USER="${NEW_USER:-ldfa}" SSH_PORT="${SSH_PORT:-50822}" TIMEZONE="${TIMEZONE:-Europe/Paris}" LOCALE="${LOCALE:-fr_FR.UTF-8}" INSTALL_FAIL2BAN="${INSTALL_FAIL2BAN:-ask}" # ask (question), 1 (oui), 0 (non) # --- Fonctions utilitaires --- log() { printf '\033[1;32m[+]\033[0m %s\n' "$*"; } warn() { printf '\033[1;33m[!]\033[0m %s\n' "$*" >&2; } die() { printf '\033[1;31m[x]\033[0m %s\n' "$*" >&2; exit 1; } usage() { cat < 65535 )); then die "Port SSH invalide : ${SSH_PORT}" fi } # --- Étapes --- update_system() { log "Mise à jour du système" export DEBIAN_FRONTEND=noninteractive apt-get update apt-get -y dist-upgrade apt-get -y install curl wget git sudo locales unattended-upgrades apt-get -y autoremove } enable_unattended_upgrades() { local conf=/etc/apt/apt.conf.d/20auto-upgrades if [[ -f $conf ]] && grep -q 'Unattended-Upgrade "1"' "$conf"; then log "unattended-upgrades déjà activé" return fi log "Activation des mises à jour de sécurité automatiques" cat > "$conf" <<'EOF' APT::Periodic::Update-Package-Lists "1"; APT::Periodic::Unattended-Upgrade "1"; EOF } create_user() { if id "$NEW_USER" &>/dev/null; then log "L'utilisateur ${NEW_USER} existe déjà" else log "Création de l'utilisateur ${NEW_USER} (mot de passe demandé)" adduser --gecos "" "$NEW_USER" fi usermod -aG sudo "$NEW_USER" } copy_ssh_keys() { local src=/root/.ssh/authorized_keys local home dest home="$(getent passwd "$NEW_USER" | cut -d: -f6)" dest="${home}/.ssh/authorized_keys" if [[ ! -f $src ]]; then warn "${src} introuvable : clés SSH non copiées" return fi if [[ -f $dest ]]; then log "${dest} existe déjà : on n'y touche pas" return fi log "Copie des clés SSH vers ${NEW_USER}" install -d -m 700 -o "$NEW_USER" -g "$NEW_USER" "${home}/.ssh" install -m 600 -o "$NEW_USER" -g "$NEW_USER" "$src" "$dest" } configure_ssh() { local conf=/etc/ssh/sshd_config.d/10-custom-port.conf log "Configuration du port SSH : ${SSH_PORT}" [[ -d /etc/ssh/sshd_config.d ]] || die "/etc/ssh/sshd_config.d absent (Debian < 11 ?)" printf 'Port %s\n' "$SSH_PORT" > "$conf" # Vérifie la configuration AVANT de redémarrer pour éviter de se couper l'accès sshd -t || { rm -f "$conf"; die "Configuration sshd invalide, modification annulée"; } # Sur les Debian récentes, ssh.socket impose le port : on revient à ssh.service if systemctl list-unit-files ssh.socket &>/dev/null; then systemctl disable --now ssh.socket 2>/dev/null || true fi systemctl enable ssh.service systemctl restart ssh.service systemctl --no-pager status ssh.service || true warn "Ouvrez le port ${SSH_PORT} dans votre pare-feu si nécessaire." warn "Testez la connexion dans un NOUVEAU terminal avant de fermer cette session." } install_fail2ban() { if [[ $INSTALL_FAIL2BAN == ask ]]; then if [[ -t 0 ]]; then read -r -p "Installer et configurer fail2ban ? [o/N] " answer [[ $answer =~ ^[oOyY]$ ]] && INSTALL_FAIL2BAN=1 || INSTALL_FAIL2BAN=0 else INSTALL_FAIL2BAN=0 fi fi if [[ $INSTALL_FAIL2BAN != 1 ]]; then log "fail2ban ignoré" return fi log "Installation de fail2ban" DEBIAN_FRONTEND=noninteractive apt-get -y install fail2ban # La jail sshd surveille le port 22 par défaut : on l'aligne sur le port choisi cat > /etc/fail2ban/jail.d/sshd-custom.conf <> "$file" <<'EOF' # >>> post-install aliases >>> export LS_OPTIONS='--color=auto' eval "$(dircolors)" alias ls='ls $LS_OPTIONS' alias ll='ls $LS_OPTIONS -lah' alias l='ls $LS_OPTIONS -lA' # <<< post-install aliases <<< EOF } configure_bashrc() { local home home="$(getent passwd "$NEW_USER" | cut -d: -f6)" add_shell_aliases /root/.bashrc add_shell_aliases "${home}/.bashrc" } configure_timezone() { log "Fuseau horaire : ${TIMEZONE}" if command -v timedatectl &>/dev/null; then timedatectl set-timezone "$TIMEZONE" else ln -sf "/usr/share/zoneinfo/${TIMEZONE}" /etc/localtime fi } configure_locale() { log "Locale : ${LOCALE}" sed -i "s/^# *\(${LOCALE} UTF-8\)/\1/" /etc/locale.gen locale-gen update-locale LANG="$LOCALE" } ask_reboot() { log "Terminé." if [[ -t 0 ]]; then read -r -p "Redémarrer maintenant ? [o/N] " answer if [[ $answer =~ ^[oOyY]$ ]]; then reboot fi else warn "Un redémarrage est recommandé pour appliquer la locale." fi } main() { while getopts ":u:p:fh" opt; do case $opt in u) NEW_USER="$OPTARG" ;; p) SSH_PORT="$OPTARG" ;; f) INSTALL_FAIL2BAN=1 ;; h) usage; exit 0 ;; *) usage >&2; exit 1 ;; esac done check_prerequisites update_system enable_unattended_upgrades create_user copy_ssh_keys configure_ssh install_fail2ban configure_bashrc configure_timezone configure_locale ask_reboot } main "$@"