docs 📝: Add Fail2Ban integration tasks to README and directory structure.
Some checks failed
ansible-lint / Ansible Lint (push) Failing after 6s
Gitleaks Scan / gitleaks (push) Successful in 4s
Markdown Lint / markdown-lint (push) Successful in 6s

Updated the README with instructions on integrating Fail2Ban and modified the directory structure to accommodate new files related to this integration.
This commit is contained in:
2026-02-23 19:36:36 +01:00
parent 3afa853d09
commit d3527c14e4
2 changed files with 65 additions and 40 deletions

View File

@@ -27,6 +27,7 @@
| Logrotate protection | ✅ | ✅ | ✅ |
| Powertop auto-tune | ✅ | ✅ | ✅ |
| Utilities | ✅ | ✅ | ✅ |
| Fail2Ban Integration | ✅ | ✅ | ✅ |
## 📂 Directory Structure
@@ -40,6 +41,7 @@ ansible_role_proxmox_provision/
├── meta/ # Role metadata
│ └── main.yml
├── tasks/ # Main role tasks
│ ├── fail2ban.yml # Fail2Ban integration tasks
│ ├── logrotate.yml # logrotate setup
│ ├── main.yml # Core tasks
│ ├── powertop.yml # powertop setup
@@ -69,6 +71,7 @@ proxmox_enable_powertop: true
## Logrotate
proxmox_logrotate_maxsize: "100M"
proxmox_logrotate_rotate: 7
...
```
## Example usage

View File

@@ -3,35 +3,65 @@
# Deploy Fail2Ban integrated with Proxmox Firewall
# -------------------------------------------------
#################################################
# Detect cluster
#################################################
- name: fail2ban | Detect Proxmox cluster
ansible.builtin.stat:
path: /etc/pve/corosync.conf
register: cluster_status
- name: fail2ban | Set cluster fact
ansible.builtin.set_fact:
pve_clustered: "{{ cluster_status.stat.exists }}"
#################################################
# Determine Correct Firewall File
#################################################
- name: fail2ban | Get Proxmox node name
ansible.builtin.command: hostname
register: pve_node
changed_when: false
- name: fail2ban | Set firewall config path
ansible.builtin.set_fact:
pve_firewall_config: >-
{{
'/etc/pve/firewall/cluster.fw'
if pve_clustered
else '/etc/pve/firewall/' + pve_node.stdout + '.fw'
}}
#################################################
# Detect firewall configuration
#################################################
- name: fail2ban | Check if cluster firewall config exists
- name: fail2ban | Check firewall config exists
ansible.builtin.stat:
path: /etc/pve/firewall/cluster.fw
register: cluster_fw
path: "{{ pve_firewall_config }}"
register: fw_stat
- name: fail2ban | Read cluster firewall config
slurp:
src: /etc/pve/firewall/cluster.fw
register: cluster_fw_content
when: cluster_fw.stat.exists
- name: fail2ban | Read firewall config
ansible.builtin.slurp:
src: "{{ pve_firewall_config }}"
register: fw_content
when: fw_stat.stat.exists
- name: fail2ban | Determine if firewall enabled
ansible.builtin.set_fact:
pve_firewall_enabled: >-
{{
cluster_fw.stat.exists and
(cluster_fw_content.content | b64decode)
is search('enable:\s*1')
fw_stat.stat.exists and
(fw_content.content | b64decode) is search('enable:\s*1')
}}
- name: fail2ban | Abort if firewall not enabled
ansible.builtin.fail:
- name: fail2ban | Warn if firewall not enabled
ansible.builtin.debug:
msg: >
Proxmox firewall is not enabled at Datacenter level.
Enable it before deploying Fail2Ban integration.
WARNING: Proxmox firewall is disabled in configuration.
Fail2Ban will not actively block traffic.
when: not pve_firewall_enabled
#################################################
@@ -49,20 +79,7 @@
msg: >
Proxmox firewall service is not running.
Run: systemctl enable --now pve-firewall
when: "'Status: enabled' not in pve_fw_status.stdout"
#################################################
# Detect cluster
#################################################
- name: fail2ban | Detect Proxmox cluster
ansible.builtin.stat:
path: /etc/pve/corosync.conf
register: cluster_status
- name: fail2ban | Set cluster fact
ansible.builtin.set_fact:
pve_clustered: "{{ cluster_status.stat.exists }}"
when: pve_fw_status.rc != 0
#################################################
# Corosync safety validation
@@ -82,8 +99,7 @@
Refusing to continue to prevent cluster outage.
when:
- cluster_status.stat.exists
- compiled_fw.stdout is search('5404')
- compiled_fw.stdout is search('DROP')
- compiled_fw.stdout is search('5404.*DROP|5405.*DROP')
#################################################
# Install Fail2Ban
@@ -96,32 +112,36 @@
update_cache: true
#################################################
# Create Proxmox firewall IPSet (cluster-wide)
# Create Proxmox firewall IPSet
#################################################
- name: fail2ban | Ensure firewall cluster config exists
- name: fail2ban | Ensure firewall directory exists
ansible.builtin.file:
path: /etc/pve/firewall
state: directory
when: pve_clustered
- name: fail2ban | Add Fail2Ban IPSet to cluster firewall
ansible.builtin.blockinfile:
path: /etc/pve/firewall/cluster.fw
path: "{{ pve_firewall_config }}"
marker: "# {mark} ANSIBLE FAIL2BAN IPSET"
block: |
[IPSET {{ f2b_ipset_name }}]
comment: Fail2Ban dynamic blacklist
create: true
when: pve_clustered
- name: fail2ban | Ensure RULES section exists
ansible.builtin.blockinfile:
path: "{{ pve_firewall_config }}"
marker: "# {mark} ANSIBLE RULES HEADER"
block: |
[RULES]
- name: fail2ban | Add drop rule for Fail2Ban IPSet
ansible.builtin.blockinfile:
path: /etc/pve/firewall/cluster.fw
path: "{{ pve_firewall_config }}"
marker: "# {mark} ANSIBLE FAIL2BAN RULE"
block: |
[RULES]
IN DROP -source +{{ f2b_ipset_name }}
when: pve_clustered
- name: fail2ban | Extract corosync ring0 address
ansible.builtin.shell: grep ring0_addr /etc/pve/corosync.conf | awk '{print $2}'
@@ -172,7 +192,7 @@
bantime.max = {{ f2b_bantime_max }}
backend = systemd
banaction = proxmox-fw
ignoreip = 127.0.0.1/8 {{ corosync_ip.stdout | default('') }} 192.168.2.0/24
ignoreip = 127.0.0.1/8{% if pve_clustered %} {{ corosync_ip.stdout }}{% endif %} 192.168.2.0/24
#################################################
# SSH
@@ -233,6 +253,8 @@
- name: fail2ban | Reload Proxmox firewall
ansible.builtin.command: pve-firewall reload
when: fw_stat.changed or
"'ANSIBLE FAIL2BAN' in fw_content.content | default('')"
changed_when: false
#################################################