--- # ============================================================================= # BASE SETUP ROLE # ============================================================================= # ========== System Update ========== - name: Update and upgrade apt packages (full upgrade) apt: upgrade: full update_cache: yes cache_valid_time: 3600 become: yes tags: [deploy_base, always] - name: Install base packages apt: name: "{{ base_packages }}" state: present update_cache: yes become: yes tags: [deploy_base, always] - name: Remove unused packages apt: autoremove: yes autoclean: yes become: yes tags: [deploy_base] # ========== System Configuration ========== - name: Disable IPv6 via sysctl sysctl: name: "{{ item.name }}" value: "{{ item.value }}" sysctl_set: yes state: present reload: yes loop: - { name: 'net.ipv6.conf.all.disable_ipv6', value: '1' } - { name: 'net.ipv6.conf.default.disable_ipv6', value: '1' } become: yes tags: [deploy_base] - name: Ensure /root/.bashrc exists file: path: /root/.bashrc state: touch mode: '0644' become: yes tags: [deploy_base] - name: Add custom aliases and environment to ~/.bashrc blockinfile: path: /root/.bashrc marker: "# {mark} ANSIBLE MANAGED BLOCK: CUSTOM ALIASES AND ENV" block: | # Работа с файлами alias rm='rm -i' # Удалить с подтверждением alias cp='cp -i' # Копировать с подтверждением alias mv='mv -i' # Переместить с подтверждением # ls - вывод списка файлов alias ls='ls --color=auto' # Цветной вывод alias ll='ls -la' # Показывать скрытые файлы и представлять вывод в виде списка alias l.='ls -d .* --color=auto' # Показать только скрытые файлы # mount - монтирование разделов alias mount='mount | column -t' # Вывод mount читаемым # История alias h='history' # История команд bash alias c='clear' # Очистить окно терминала # Дата и время alias now='date +%T' # Время сейчас alias nowdate='date +%d-%m-%Y' # Только дата # Сеть alias ping5='ping -c 5' # Посылать только пять запросов alias ports='netstat -tulanp' # Открытые порты # Работа с пакетами alias update='sudo apt update && sudo apt upgrade' # Обновление одной командой # Работа с системой alias meminfo='free -m -l -t' # Сколько памяти занято alias psmem='ps auxf | sort -nr -k 4 | head -10' # 10 процессов с самой большой нагрузкой на память # Переменные окружения export DISPLAY="{{ x11_display_host }}:0" export HISTTIMEFORMAT='%F %T ' owner: root mode: '0644' become: yes tags: [deploy_base] - name: Configure timezone timezone: name: "{{ timezone }}" become: yes tags: [deploy_base] - name: Configure locale locale_gen: name: "{{ system_locale }}" state: present become: yes tags: [deploy_base] - name: Set default locale lineinfile: path: /etc/default/locale line: "LANG={{ system_locale }}" state: present create: yes become: yes tags: [deploy_base] - name: Ensure required directories exist file: path: "{{ item }}" state: directory mode: '0755' loop: "{{ custom_directories | default([]) }}" become: yes tags: [deploy_base] # ========== SSH Configuration ========== - name: Ensure SSH directory exists for root file: path: /root/.ssh state: directory mode: '0700' become: yes tags: [deploy_base, ssh] - name: Add authorized keys for root (exclusive) authorized_key: user: root state: present key: "{{ item }}" exclusive: yes loop: "{{ ssh_public_keys }}" become: yes tags: [deploy_base, ssh] # ========== Create Admin User zailon ========== - name: Create admin user zailon user: name: zailon shell: /bin/bash groups: sudo append: yes create_home: yes state: present become: yes tags: [deploy_base, users] - name: Set password for zailon from vault user: name: zailon password: "{{ vault_zailon_password | password_hash('sha512') }}" update_password: always become: yes no_log: true tags: [deploy_base, users] - name: Configure passwordless sudo for zailon copy: content: "zailon ALL=(ALL) NOPASSWD: ALL\n" dest: /etc/sudoers.d/zailon mode: '0440' owner: root group: root validate: 'visudo -cf %s' become: yes tags: [deploy_base, users] - name: Create .ssh directory for zailon file: path: /home/zailon/.ssh state: directory mode: '0700' owner: zailon group: zailon become: yes tags: [deploy_base, users] - name: Deploy authorized_keys for zailon copy: content: "{{ ssh_public_keys | join('\n') }}\n" dest: /home/zailon/.ssh/authorized_keys owner: zailon group: zailon mode: '0600' become: yes tags: [deploy_base, users] - name: Copy bashrc to zailon copy: src: /root/.bashrc dest: /home/zailon/.bashrc owner: zailon group: zailon mode: '0644' remote_src: yes become: yes tags: [deploy_base, users] # ========== SSH Security Hardening ========== - name: Configure SSH security lineinfile: path: /etc/ssh/sshd_config regexp: "{{ item.regexp }}" line: "{{ item.line }}" state: present validate: 'sshd -t -f %s' loop: - { regexp: '^PasswordAuthentication', line: 'PasswordAuthentication no' } - { regexp: '^PermitRootLogin', line: 'PermitRootLogin yes' } - { regexp: '^PubkeyAuthentication', line: 'PubkeyAuthentication yes' } notify: restart ssh become: yes tags: [deploy_base, ssh] # ========== Node Exporter Installation ========== - name: Create node_exporter system user user: name: node_exporter system: yes shell: /bin/false create_home: no become: yes tags: [node_exporter] - name: Set node_exporter architecture set_fact: node_exporter_arch: "{{ 'amd64' if ansible_architecture == 'x86_64' else 'arm64' if ansible_architecture == 'aarch64' else ansible_architecture }}" tags: [node_exporter] - name: Download node_exporter get_url: url: "https://github.com/prometheus/node_exporter/releases/download/v1.8.2/node_exporter-1.8.2.linux-{{ node_exporter_arch }}.tar.gz" dest: /tmp/node_exporter.tar.gz mode: '0644' timeout: 60 when: node_exporter_arch in ['amd64', 'arm64'] become: yes tags: [node_exporter] - name: Fail on unsupported architecture fail: msg: "Unsupported architecture {{ ansible_architecture }} for node_exporter" when: node_exporter_arch not in ['amd64', 'arm64'] tags: [node_exporter] - name: Create temporary extraction directory file: path: /tmp/node_exporter_temp state: directory mode: '0755' become: yes tags: [node_exporter] - name: Extract node_exporter unarchive: src: /tmp/node_exporter.tar.gz dest: /tmp/node_exporter_temp remote_src: yes creates: /tmp/node_exporter_temp/node_exporter-1.8.2.linux-amd64/node_exporter become: yes tags: [node_exporter] - name: Install node_exporter binary copy: src: /tmp/node_exporter_temp/node_exporter-1.8.2.linux-amd64/node_exporter dest: /usr/local/bin/node_exporter owner: root group: root mode: '0755' remote_src: yes become: yes notify: restart node_exporter tags: [node_exporter] - name: Clean up temporary files file: path: "{{ item }}" state: absent loop: - /tmp/node_exporter.tar.gz - /tmp/node_exporter_temp become: yes tags: [node_exporter] - name: Create textfile collector directory file: path: /var/lib/node_exporter/textfile_collector state: directory owner: node_exporter group: node_exporter mode: '0755' become: yes tags: [node_exporter] - name: Deploy node_exporter systemd service copy: content: | [Unit] Description=Prometheus Node Exporter Documentation=https://github.com/prometheus/node_exporter After=network.target [Service] Type=simple User=node_exporter Group=node_exporter ExecStart=/usr/local/bin/node_exporter \ --collector.systemd \ --collector.processes \ --collector.cpu \ --collector.meminfo \ --collector.diskstats \ --collector.filesystem \ --collector.loadavg \ --collector.time \ --collector.textfile.directory=/var/lib/node_exporter/textfile_collector \ --no-collector.arp \ --no-collector.netdev \ --web.listen-address=0.0.0.0:9100 \ --web.telemetry-path=/metrics Restart=always RestartSec=5 # Security settings NoNewPrivileges=yes ProtectSystem=strict ProtectHome=yes PrivateTmp=yes ProtectControlGroups=yes ProtectKernelModules=yes ProtectKernelTunables=yes LockPersonality=yes RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX [Install] WantedBy=multi-user.target dest: /etc/systemd/system/node_exporter.service owner: root group: root mode: '0644' become: yes notify: restart node_exporter tags: [node_exporter] - name: Start and enable node_exporter systemd: name: node_exporter state: started enabled: yes daemon_reload: yes become: yes tags: [node_exporter] - name: Wait for node_exporter to start wait_for: host: localhost port: 9100 timeout: 30 state: started delay: 5 become: yes tags: [node_exporter] - name: Verify node_exporter is responding uri: url: http://localhost:9100/metrics status_code: 200 timeout: 10 register: node_exporter_check become: yes tags: [node_exporter] - name: Show node_exporter status debug: msg: "Node Exporter is running and responding on port 9100" when: node_exporter_check.status == 200 tags: [node_exporter] - name: Allow port 9100 in ufw (if enabled) ufw: rule: allow port: 9100 proto: tcp comment: "Prometheus Node Exporter" when: - ansible_facts.services["ufw.service"] is defined - ansible_facts.services["ufw.service"]["state"] == "running" become: yes tags: [node_exporter]