--- - name: Bootstrap host for Ansible automation hosts: all become: true gather_facts: false vars: category: maintenance subcategory: bootstrap automation_user: "{{ lookup('env', 'SSH_USER') | default('automation', true) }}" ssh_public_key_path: "/app/ssh_keys/id_rsa.pub" tasks: - name: Detect OS type raw: | if command -v apk >/dev/null 2>&1; then echo "alpine" elif command -v pkg >/dev/null 2>&1 && [ -f /etc/freebsd-update.conf ]; then echo "freebsd" elif [ -f /etc/debian_version ]; then echo "debian" elif [ -f /etc/redhat-release ]; then echo "redhat" else echo "unknown" fi register: os_type_raw changed_when: false - name: Detect OS variant (Armbian, Raspbian, etc.) raw: | if [ -f /etc/armbian-release ]; then echo "armbian" elif [ -f /etc/rpi-issue ] || grep -qi "raspberry" /proc/cpuinfo 2>/dev/null; then echo "raspbian" else echo "standard" fi register: os_variant_raw changed_when: false - name: Set OS type fact set_fact: os_type: "{{ os_type_raw.stdout | trim }}" os_variant: "{{ os_variant_raw.stdout | trim }}" - name: Display detected OS debug: msg: "[1/7] OS détecté: {{ os_type }} ({{ os_variant }})" - name: Check if automation user exists raw: id {{ automation_user }} 2>/dev/null && echo "exists" || echo "not_exists" register: user_check changed_when: false - name: Display user status debug: msg: "[2/7] Utilisateur {{ automation_user }}: {{ 'existant' if 'exists' in user_check.stdout else 'à créer' }}" - name: Create automation user (Debian/Ubuntu) raw: useradd -m -s /bin/bash {{ automation_user }} || useradd -m -s /bin/sh {{ automation_user }} when: - "'not_exists' in user_check.stdout" - os_type == "debian" - name: Create automation user (Alpine) raw: adduser -D {{ automation_user }} when: - "'not_exists' in user_check.stdout" - os_type == "alpine" - name: Create automation user (FreeBSD) raw: pw useradd {{ automation_user }} -m -s /bin/sh when: - "'not_exists' in user_check.stdout" - os_type == "freebsd" - name: Display user creation result debug: msg: "[3/7] Utilisateur {{ automation_user }} configuré" - name: Unlock user account raw: | if command -v passwd >/dev/null 2>&1; then passwd -u {{ automation_user }} 2>/dev/null || true fi if command -v usermod >/dev/null 2>&1; then usermod -U {{ automation_user }} 2>/dev/null || true fi changed_when: false - name: Get home directory raw: "getent passwd {{ automation_user }} | cut -d: -f6 || echo /home/{{ automation_user }}" register: home_dir_raw changed_when: false - name: Set home directory fact set_fact: home_dir: "{{ home_dir_raw.stdout | trim }}" - name: Create .ssh directory raw: | mkdir -p {{ home_dir }}/.ssh chown {{ automation_user }}:{{ automation_user }} {{ home_dir }}/.ssh chmod 700 {{ home_dir }}/.ssh changed_when: false - name: Read local SSH public key delegate_to: localhost become: false slurp: src: "{{ ssh_public_key_path }}" register: ssh_pub_key ignore_errors: true - name: Try alternate SSH key paths delegate_to: localhost become: false slurp: src: "{{ item }}" register: ssh_pub_key_alt loop: - "/app/ssh_keys/id_ed25519.pub" - "/app/ssh_keys/id_automation_ansible.pub" - "{{ lookup('env', 'HOME') }}/.ssh/id_rsa.pub" when: ssh_pub_key.failed | default(false) ignore_errors: true - name: Set SSH public key content set_fact: ssh_key_content: "{{ (ssh_pub_key.content | b64decode | trim) if not (ssh_pub_key.failed | default(false)) else (ssh_pub_key_alt.results | selectattr('content', 'defined') | map(attribute='content') | first | b64decode | trim) }}" when: not (ssh_pub_key.failed | default(false)) or (ssh_pub_key_alt.results | selectattr('content', 'defined') | list | length > 0) - name: Install SSH public key raw: | cat > {{ home_dir }}/.ssh/authorized_keys << 'SSHKEY_EOF' {{ ssh_key_content }} SSHKEY_EOF chown {{ automation_user }}:{{ automation_user }} {{ home_dir }}/.ssh/authorized_keys chmod 600 {{ home_dir }}/.ssh/authorized_keys when: ssh_key_content is defined - name: Verify authorized_keys raw: test -s {{ home_dir }}/.ssh/authorized_keys && wc -l < {{ home_dir }}/.ssh/authorized_keys || echo "0" register: auth_keys_count changed_when: false - name: Display SSH key status debug: msg: "[4/7] Clé SSH installée ({{ auth_keys_count.stdout | trim }} clé(s))" - name: Install sudo (Debian/Ubuntu) raw: | if ! command -v sudo >/dev/null 2>&1; then apt-get update -qq && apt-get install -y sudo fi when: os_type == "debian" - name: Install sudo (Alpine) raw: | if ! command -v sudo >/dev/null 2>&1; then apk add --no-cache sudo fi when: os_type == "alpine" - name: Install sudo (FreeBSD) raw: | if ! command -v sudo >/dev/null 2>&1; then pkg install -y sudo fi when: os_type == "freebsd" - name: Display sudo status debug: msg: "[5/7] sudo installé/vérifié" - name: Configure sudoers raw: | mkdir -p /etc/sudoers.d echo "{{ automation_user }} ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/automation chmod 440 /etc/sudoers.d/automation changed_when: false - name: Display sudoers status debug: msg: "[6/7] Sudoers configuré: /etc/sudoers.d/automation" - name: Install Python3 (Debian/Ubuntu) raw: | if ! command -v python3 >/dev/null 2>&1; then apt-get update -qq && apt-get install -y python3 fi when: os_type == "debian" - name: Install Python3 (Alpine) raw: | if ! command -v python3 >/dev/null 2>&1; then apk add --no-cache python3 fi when: os_type == "alpine" - name: Install Python3 (FreeBSD) raw: | if ! command -v python3 >/dev/null 2>&1; then pkg install -y python3 fi when: os_type == "freebsd" - name: Get Python version raw: python3 --version 2>&1 || echo "N/A" register: python_version changed_when: false - name: Display Python status debug: msg: "[7/7] Python3 installé: {{ python_version.stdout | trim }}" - name: Display bootstrap summary debug: msg: | ═══════════════════════════════════════ Bootstrap terminé avec succès! ═══════════════════════════════════════ Host: {{ inventory_hostname }} OS Type: {{ os_type }} ({{ os_variant }}) User: {{ automation_user }} Home: {{ home_dir }} SSH Keys: {{ auth_keys_count.stdout | trim }} Python: {{ python_version.stdout | trim }} ═══════════════════════════════════════