From 7ef37036bc936dcb3a09ec82206d72c19a36af1a Mon Sep 17 00:00:00 2001 From: okxlin <61420215+okxlin@users.noreply.github.com> Date: Wed, 24 Jun 2026 21:27:19 +0800 Subject: [PATCH] Add LinuxServer Fail2ban adapter --- apps/fail2ban-linuxserver/1.1.0/.env.sample | 5 ++ apps/fail2ban-linuxserver/1.1.0/data.yml | 75 ++++++++++++++++++ apps/fail2ban-linuxserver/1.1.0/data/.gitkeep | 0 .../1.1.0/docker-compose.yml | 19 +++++ .../1.1.0/scripts/init.sh | 4 + .../1.1.0/scripts/uninstall.sh | 2 + .../1.1.0/scripts/upgrade.sh | 4 + apps/fail2ban-linuxserver/README.md | 44 ++++++++++ apps/fail2ban-linuxserver/data.yml | 30 +++++++ apps/fail2ban-linuxserver/latest/.env.sample | 5 ++ apps/fail2ban-linuxserver/latest/data.yml | 75 ++++++++++++++++++ .../fail2ban-linuxserver/latest/data/.gitkeep | 0 .../latest/docker-compose.yml | 19 +++++ .../latest/scripts/init.sh | 4 + .../latest/scripts/uninstall.sh | 2 + .../latest/scripts/upgrade.sh | 4 + apps/fail2ban-linuxserver/logo.png | Bin 0 -> 6932 bytes 17 files changed, 292 insertions(+) create mode 100644 apps/fail2ban-linuxserver/1.1.0/.env.sample create mode 100644 apps/fail2ban-linuxserver/1.1.0/data.yml create mode 100644 apps/fail2ban-linuxserver/1.1.0/data/.gitkeep create mode 100644 apps/fail2ban-linuxserver/1.1.0/docker-compose.yml create mode 100755 apps/fail2ban-linuxserver/1.1.0/scripts/init.sh create mode 100755 apps/fail2ban-linuxserver/1.1.0/scripts/uninstall.sh create mode 100755 apps/fail2ban-linuxserver/1.1.0/scripts/upgrade.sh create mode 100644 apps/fail2ban-linuxserver/README.md create mode 100644 apps/fail2ban-linuxserver/data.yml create mode 100644 apps/fail2ban-linuxserver/latest/.env.sample create mode 100644 apps/fail2ban-linuxserver/latest/data.yml create mode 100644 apps/fail2ban-linuxserver/latest/data/.gitkeep create mode 100644 apps/fail2ban-linuxserver/latest/docker-compose.yml create mode 100755 apps/fail2ban-linuxserver/latest/scripts/init.sh create mode 100755 apps/fail2ban-linuxserver/latest/scripts/uninstall.sh create mode 100755 apps/fail2ban-linuxserver/latest/scripts/upgrade.sh create mode 100644 apps/fail2ban-linuxserver/logo.png diff --git a/apps/fail2ban-linuxserver/1.1.0/.env.sample b/apps/fail2ban-linuxserver/1.1.0/.env.sample new file mode 100644 index 000000000..7dcbfb785 --- /dev/null +++ b/apps/fail2ban-linuxserver/1.1.0/.env.sample @@ -0,0 +1,5 @@ +CONTAINER_NAME= +CONFIG_PATH=./data/config +HOST_LOG_PATH=/var/log +VERBOSITY=-vv +TIME_ZONE=Asia/Shanghai diff --git a/apps/fail2ban-linuxserver/1.1.0/data.yml b/apps/fail2ban-linuxserver/1.1.0/data.yml new file mode 100644 index 000000000..df7db9b8e --- /dev/null +++ b/apps/fail2ban-linuxserver/1.1.0/data.yml @@ -0,0 +1,75 @@ +additionalProperties: + formFields: + - default: ./data/config + edit: true + envKey: CONFIG_PATH + labelEn: Config folder path + labelZh: 配置文件路径 + label: + en: Config folder path + zh: 配置文件路径 + zh-Hant: 設定檔資料夾路徑 + ja: 設定フォルダーのパス + ko: 설정 폴더 경로 + ru: Путь к папке конфигурации + ms: Laluan folder konfigurasi + pt-br: Caminho da pasta de configuração + required: true + type: text + - default: /var/log + edit: true + envKey: HOST_LOG_PATH + labelEn: Host log path + labelZh: 主机日志路径 + label: + en: Host log path + zh: 主机日志路径 + zh-Hant: 主機日誌路徑 + ja: ホストログパス + ko: 호스트 로그 경로 + ru: Путь журналов хоста + ms: Laluan log hos + pt-br: Caminho de logs do host + required: true + type: text + - default: "-vv" + edit: true + envKey: VERBOSITY + labelEn: Log verbosity + labelZh: 日志详细级别 + label: + en: Log verbosity + zh: 日志详细级别 + zh-Hant: 日誌詳細層級 + ja: ログ詳細レベル + ko: 로그 상세 수준 + ru: Подробность журнала + ms: Tahap keterperincian log + pt-br: Nivel de detalhamento do log + required: true + type: select + values: + - label: "-v" + value: "-v" + - label: "-vv" + value: "-vv" + - label: "-vvv" + value: "-vvv" + - label: "-vvvv" + value: "-vvvv" + - default: Asia/Shanghai + edit: true + envKey: TIME_ZONE + labelEn: Time zone + labelZh: 时区 + label: + en: Time zone + zh: 时区 + zh-Hant: 時區 + ja: タイムゾーン + ko: 시간대 + ru: Часовой пояс + ms: Zon waktu + pt-br: Fuso horário + required: true + type: text diff --git a/apps/fail2ban-linuxserver/1.1.0/data/.gitkeep b/apps/fail2ban-linuxserver/1.1.0/data/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/fail2ban-linuxserver/1.1.0/docker-compose.yml b/apps/fail2ban-linuxserver/1.1.0/docker-compose.yml new file mode 100644 index 000000000..b56dfb66b --- /dev/null +++ b/apps/fail2ban-linuxserver/1.1.0/docker-compose.yml @@ -0,0 +1,19 @@ +services: + fail2ban: + image: "linuxserver/fail2ban:1.1.0" + container_name: ${CONTAINER_NAME} + restart: always + network_mode: host + cap_add: + - NET_ADMIN + - NET_RAW + volumes: + - "${CONFIG_PATH}:/config" + - "${HOST_LOG_PATH}:/var/log:ro" + environment: + - PUID=1000 + - PGID=1000 + - TZ=${TIME_ZONE} + - VERBOSITY=${VERBOSITY} + labels: + createdBy: "Apps" diff --git a/apps/fail2ban-linuxserver/1.1.0/scripts/init.sh b/apps/fail2ban-linuxserver/1.1.0/scripts/init.sh new file mode 100755 index 000000000..71fd851bd --- /dev/null +++ b/apps/fail2ban-linuxserver/1.1.0/scripts/init.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -euo pipefail +mkdir -p ./data/config +chown -R 1000:1000 ./data 2>/dev/null || true diff --git a/apps/fail2ban-linuxserver/1.1.0/scripts/uninstall.sh b/apps/fail2ban-linuxserver/1.1.0/scripts/uninstall.sh new file mode 100755 index 000000000..ab8a8d674 --- /dev/null +++ b/apps/fail2ban-linuxserver/1.1.0/scripts/uninstall.sh @@ -0,0 +1,2 @@ +#!/bin/bash +docker-compose down --volumes diff --git a/apps/fail2ban-linuxserver/1.1.0/scripts/upgrade.sh b/apps/fail2ban-linuxserver/1.1.0/scripts/upgrade.sh new file mode 100755 index 000000000..71fd851bd --- /dev/null +++ b/apps/fail2ban-linuxserver/1.1.0/scripts/upgrade.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -euo pipefail +mkdir -p ./data/config +chown -R 1000:1000 ./data 2>/dev/null || true diff --git a/apps/fail2ban-linuxserver/README.md b/apps/fail2ban-linuxserver/README.md new file mode 100644 index 000000000..983a7bde4 --- /dev/null +++ b/apps/fail2ban-linuxserver/README.md @@ -0,0 +1,44 @@ +# Fail2ban LinuxServer + +## 产品介绍 + +Fail2ban LinuxServer 使用 LinuxServer.io 维护的 `linuxserver/fail2ban` 镜像,提供 Fail2ban 主机入侵防护服务 能力。 + +## 主要功能 + +- 提供 日志监控和封禁规则 能力 +- 持久化保存配置和业务数据 +- 使用安装表单配置数据路径、主机日志路径和日志级别 +- 支持自定义时区 + +## 访问说明 + +Fail2ban 没有 Web 界面。安装完成后,在配置目录中编辑 jail 配置并查看 `/config/log/fail2ban/fail2ban.log`。 + +## 运行说明 + +该应用使用 host network,并需要 `NET_ADMIN`、`NET_RAW` 权限读取日志并管理封禁规则。默认 LinuxServer 配置中的 jail 处于禁用状态,请仅在确认日志路径和封禁规则后启用需要的 jail。 + +## Introduction + +Fail2ban LinuxServer uses the LinuxServer.io maintained `linuxserver/fail2ban` image for log monitoring and ban rules. + +## Features + +- Provide log monitoring and ban rules +- Persist configuration and application data +- Configure data paths, host log path, and log verbosity from the install form +- Configure the container time zone + +## Access + +Fail2ban does not provide a web interface. After installation, edit jail files in the config directory and check `/config/log/fail2ban/fail2ban.log`. + +## Runtime Notes + +This app uses host networking and requires `NET_ADMIN` and `NET_RAW` so it can read logs and manage ban rules. LinuxServer's default jail configuration is disabled; enable only the jails whose log paths and ban actions you have reviewed. + +## Links + +- LinuxServer image documentation: +- Project website: diff --git a/apps/fail2ban-linuxserver/data.yml b/apps/fail2ban-linuxserver/data.yml new file mode 100644 index 000000000..a091eb433 --- /dev/null +++ b/apps/fail2ban-linuxserver/data.yml @@ -0,0 +1,30 @@ +name: Fail2ban LinuxServer +tags: +- Security +title: Fail2ban 主机入侵防护服务 +description: Fail2ban 主机入侵防护服务 +additionalProperties: + key: fail2ban-linuxserver + name: Fail2ban LinuxServer + tags: + - Security + shortDescZh: Fail2ban 主机入侵防护服务 + shortDescEn: Host intrusion prevention service maintained by LinuxServer.io + description: + en: Host intrusion prevention service maintained by LinuxServer.io + zh: Fail2ban 主机入侵防护服务 + zh-Hant: Fail2ban 主機入侵防護服務 + ja: LinuxServer.io が保守するホスト侵入防止サービス + ko: LinuxServer.io에서 유지 관리하는 호스트 침입 방지 서비스 + ru: Служба предотвращения вторжений на хост, поддерживаемая LinuxServer.io + ms: Perkhidmatan pencegahan pencerobohan hos yang diselenggara oleh LinuxServer.io + pt-br: Servico de prevencao de intrusao no host mantido pela LinuxServer.io + type: tool + crossVersionUpdate: true + limit: 0 + website: http://www.fail2ban.org/ + github: https://github.com/linuxserver/docker-fail2ban + document: https://docs.linuxserver.io/images/docker-fail2ban/ + architectures: + - amd64 + - arm64 diff --git a/apps/fail2ban-linuxserver/latest/.env.sample b/apps/fail2ban-linuxserver/latest/.env.sample new file mode 100644 index 000000000..7dcbfb785 --- /dev/null +++ b/apps/fail2ban-linuxserver/latest/.env.sample @@ -0,0 +1,5 @@ +CONTAINER_NAME= +CONFIG_PATH=./data/config +HOST_LOG_PATH=/var/log +VERBOSITY=-vv +TIME_ZONE=Asia/Shanghai diff --git a/apps/fail2ban-linuxserver/latest/data.yml b/apps/fail2ban-linuxserver/latest/data.yml new file mode 100644 index 000000000..df7db9b8e --- /dev/null +++ b/apps/fail2ban-linuxserver/latest/data.yml @@ -0,0 +1,75 @@ +additionalProperties: + formFields: + - default: ./data/config + edit: true + envKey: CONFIG_PATH + labelEn: Config folder path + labelZh: 配置文件路径 + label: + en: Config folder path + zh: 配置文件路径 + zh-Hant: 設定檔資料夾路徑 + ja: 設定フォルダーのパス + ko: 설정 폴더 경로 + ru: Путь к папке конфигурации + ms: Laluan folder konfigurasi + pt-br: Caminho da pasta de configuração + required: true + type: text + - default: /var/log + edit: true + envKey: HOST_LOG_PATH + labelEn: Host log path + labelZh: 主机日志路径 + label: + en: Host log path + zh: 主机日志路径 + zh-Hant: 主機日誌路徑 + ja: ホストログパス + ko: 호스트 로그 경로 + ru: Путь журналов хоста + ms: Laluan log hos + pt-br: Caminho de logs do host + required: true + type: text + - default: "-vv" + edit: true + envKey: VERBOSITY + labelEn: Log verbosity + labelZh: 日志详细级别 + label: + en: Log verbosity + zh: 日志详细级别 + zh-Hant: 日誌詳細層級 + ja: ログ詳細レベル + ko: 로그 상세 수준 + ru: Подробность журнала + ms: Tahap keterperincian log + pt-br: Nivel de detalhamento do log + required: true + type: select + values: + - label: "-v" + value: "-v" + - label: "-vv" + value: "-vv" + - label: "-vvv" + value: "-vvv" + - label: "-vvvv" + value: "-vvvv" + - default: Asia/Shanghai + edit: true + envKey: TIME_ZONE + labelEn: Time zone + labelZh: 时区 + label: + en: Time zone + zh: 时区 + zh-Hant: 時區 + ja: タイムゾーン + ko: 시간대 + ru: Часовой пояс + ms: Zon waktu + pt-br: Fuso horário + required: true + type: text diff --git a/apps/fail2ban-linuxserver/latest/data/.gitkeep b/apps/fail2ban-linuxserver/latest/data/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/apps/fail2ban-linuxserver/latest/docker-compose.yml b/apps/fail2ban-linuxserver/latest/docker-compose.yml new file mode 100644 index 000000000..104b389f7 --- /dev/null +++ b/apps/fail2ban-linuxserver/latest/docker-compose.yml @@ -0,0 +1,19 @@ +services: + fail2ban: + image: "linuxserver/fail2ban:latest" + container_name: ${CONTAINER_NAME} + restart: always + network_mode: host + cap_add: + - NET_ADMIN + - NET_RAW + volumes: + - "${CONFIG_PATH}:/config" + - "${HOST_LOG_PATH}:/var/log:ro" + environment: + - PUID=1000 + - PGID=1000 + - TZ=${TIME_ZONE} + - VERBOSITY=${VERBOSITY} + labels: + createdBy: "Apps" diff --git a/apps/fail2ban-linuxserver/latest/scripts/init.sh b/apps/fail2ban-linuxserver/latest/scripts/init.sh new file mode 100755 index 000000000..71fd851bd --- /dev/null +++ b/apps/fail2ban-linuxserver/latest/scripts/init.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -euo pipefail +mkdir -p ./data/config +chown -R 1000:1000 ./data 2>/dev/null || true diff --git a/apps/fail2ban-linuxserver/latest/scripts/uninstall.sh b/apps/fail2ban-linuxserver/latest/scripts/uninstall.sh new file mode 100755 index 000000000..ab8a8d674 --- /dev/null +++ b/apps/fail2ban-linuxserver/latest/scripts/uninstall.sh @@ -0,0 +1,2 @@ +#!/bin/bash +docker-compose down --volumes diff --git a/apps/fail2ban-linuxserver/latest/scripts/upgrade.sh b/apps/fail2ban-linuxserver/latest/scripts/upgrade.sh new file mode 100755 index 000000000..71fd851bd --- /dev/null +++ b/apps/fail2ban-linuxserver/latest/scripts/upgrade.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -euo pipefail +mkdir -p ./data/config +chown -R 1000:1000 ./data 2>/dev/null || true diff --git a/apps/fail2ban-linuxserver/logo.png b/apps/fail2ban-linuxserver/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..d61a28a8814477cf07d4b8b51229188ea8075b35 GIT binary patch literal 6932 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 HG46i=gQ+