--- - name: Ensure base packages ansible.builtin.package: name: - apt-transport-https - ca-certificates - curl - git - vim - ufw - fail2ban - python3 - python3-venv state: present update_cache: true - name: Harden SSH ansible.builtin.copy: dest: /etc/ssh/sshd_config.d/10-hardening.conf owner: root group: root mode: '0644' content: | PasswordAuthentication no PermitRootLogin no PubkeyAuthentication yes - name: Restart sshd ansible.builtin.service: name: ssh state: restarted - name: Ensure .ssh directory exists for ops_bridge_user ansible.builtin.file: path: "/home/{{ ops_bridge_user | default('tegwick') }}/.ssh" state: directory owner: "{{ ops_bridge_user | default('tegwick') }}" group: "{{ ops_bridge_user | default('tegwick') }}" mode: '0700' - name: Inject ops-bridge public key into authorized_keys ansible.posix.authorized_key: user: "{{ ops_bridge_user | default('tegwick') }}" key: "{{ ops_bridge_pubkey }}" comment: "ops-bridge@{{ inventory_hostname }}" state: present when: ops_bridge_pubkey is defined and ops_bridge_pubkey | length > 0 - name: Configure UFW default incoming policy ansible.builtin.ufw: state: enabled policy: deny direction: incoming - name: Allow UFW routing (required for k3s flannel pod networking) ansible.builtin.ufw: policy: allow direction: routed - name: Allow SSH in UFW ansible.builtin.ufw: rule: allow name: OpenSSH - name: Allow k3s API in UFW ansible.builtin.ufw: rule: allow port: '6443' proto: tcp - name: Allow Flannel VXLAN in UFW ansible.builtin.ufw: rule: allow port: '8472' proto: udp - name: Enable fail2ban ansible.builtin.service: name: fail2ban state: started enabled: true - name: Configure fail2ban SSH jail ansible.builtin.copy: dest: /etc/fail2ban/jail.d/sshd.conf owner: root group: root mode: '0644' content: | [sshd] enabled = true port = ssh filter = sshd maxretry = 5 bantime = 3600 findtime = 600 notify: Restart fail2ban - name: Set HISTCONTROL to ignorespace ansible.builtin.copy: dest: /etc/profile.d/histcontrol.sh owner: root group: root mode: '0644' content: | export HISTCONTROL=ignorespace - name: Set timezone community.general.timezone: name: "{{ timezone | default('UTC') }}"