Sno Station
Sno Station은 AI 에이전트를 하나의 팀으로 묶는 오픈소스 워크스테이션으로, 로컬 머신에서 에이전트 협업을 가능하게 함
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗English · Français · Deutsch · Español
Gladys Assistant external integration for Fail2Ban: the banned IPs and the failures of each jail as devices, scenes when an IP is banned or Fail2Ban stops answering, and dashboard widgets to ban and unban. It talks to Fail2Ban over SSH, on the Gladys host or on any other server.
docker exec fail2ban fail2ban-client).flowchart LR
G[Gladys Assistant] <-->|REST /api/integration/v1/* + WebSocket| I[gladys-fail2ban container]
I -->|SSH: fail2ban-client| S[Your server<br/>Fail2Ban, its jails]
I --- D[(/data<br/>SSH key, host key, bans seen)]
Fail2Ban only answers on a Unix socket of the machine it protects, which a container cannot reach. The integration logs in over SSH and runs fail2ban-client status --all (or status then status <jail> on versions before 1.1) on its own timer. Each reading is compared with the previous one: an address that appeared fires IP banned (with the time of the ban from get <jail> banip --with-time), an address that left fires IP unbanned. Every argument is validated and quoted before it reaches the remote shell.
sequenceDiagram
participant U as User
participant G as Gladys
participant I as Integration
participant S as Server (SSH)
I->>S: fail2ban-client status --all
I->>G: discovered devices (server, jails)
U->>G: creates "Fail2Ban jail sshd"
G->>I: device-created
loop every minute (30 s to 5 min)
I->>S: status --all, banip --with-time (new bans)
S-->>I: jails, counters, banned IPs
I->>G: states (banned, failures…)
I->>G: scene events (IP banned, unbanned, server down…)
end
U->>G: widget button "Ban an IP" / scene action
G->>I: widget-action / scene-action
I->>S: set <jail> banip <ip>
I-->>G: toast / outputs (no scene event: no loop)
Local ("transports": ["local"]): the catalog shows the local badge. The integration connects directly to the server you name; nothing goes through a cloud. If that server is a VPS, the SSH connection crosses the internet, encrypted. With a single channel there is no "prefer the local connection" button.
| Device | Feature | Category / type |
|---|---|---|
| Fail2Ban | IPs banned now (all jails) | counter-sensor/integer |
| Fail2Ban | Failures now (all jails) | counter-sensor/integer |
| Fail2Ban | Bans since Fail2Ban started | counter-sensor/integer |
| Fail2Ban | Jails running | counter-sensor/integer |
| Fail2Ban jail | IPs banned now, failures now | counter-sensor/integer |
| Fail2Ban jail | Bans and failures since Fail2Ban started | counter-sensor/integer |
| Fail2Ban jail | Last banned IP | text/text |
The devices are read on the integration's own timer (should_poll: false). The "since start" counters restart at zero when Fail2Ban restarts.
Triggers
ip, jail, banned_count, total_banned, ban_seconds, permanent, until, server.server, reason, message.Actions: ban an IP (or a CIDR network) in a jail, unban an IP (one jail or all), check an IP, read a summary (summary sentence).
Widgets: Fail2Ban (counters, one row per jail, Ban / Unban forms, Refresh) and Fail2Ban bans (latest bans, what is left of each, Unban).
Examples
recidive → send {{triggerEvent.data.ip}} banned until {{triggerEvent.data.until}} to your phone.Changes made by Gladys (scene actions, widget buttons) fire no trigger.
fail2ban-client without a password: see docs/en.md for the three commands (user, sudoers rule, authorized_keys).https://github.com/William-De71/gladys-fail2ban.docker build -t gladys-fail2ban .) and install it from Gladys.| Field | Default | Role |
|---|---|---|
| Address of the server | — | LAN address or host name of the Fail2Ban machine (never localhost). |
| SSH port | 22 | Port of its SSH server. |
| SSH user | — | The user allowed to run fail2ban-client. |
| Authentication | Key of the integration | Or Password. |
| SSH password | — | Secret; only with the Password authentication. |
| fail2ban-client command | sudo -n fail2ban-client | docker exec fail2ban fail2ban-client, fail2ban-client as root… |
| Host key | trusted on first use | SHA256 fingerprint(s) of the server, to pin it. |
| Jails to follow | all | sshd, recidive. |
| Reading interval | 1 minute | 30 seconds to 5 minutes. |
| Language of the texts | automatic | Device names and scene texts. |
authorized_keys on the server, then Test the connection.npm install
npm test # node --test, never touches the network
npm run lint && npm run format:check
npx github:GladysAssistant/integration-store . --skip-image-check
scripts/build-cover.sh # cover.jpg from docs/assets/cover.svg
docs/illustrations/render.sh # docs/assets/widgets.<lang>.png
node .github/scripts/release.mjs next
Locally, the SDK reads GLADYS_HOST_API_URL, GLADYS_INTEGRATION_TOKEN and GLADYS_INTEGRATION_SELECTOR; DEBUG=gladys-integration-sdk shows the SDK logs and checks every widget content. The tests drive the integration with the fake Gladys of the SDK and a fake fail2ban-client whose answers follow real ones (test/fixtures/, read on Fail2Ban 1.1.0). The rules of the project are in CLAUDE.md.
Every merge on main runs the CI, then computes the version from the Conventional Commits since the last tag: feat → minor, fix / perf → patch, ! or BREAKING CHANGE → major (a minor below 1.0.0); docs, chore, ci, test, style, refactor, build alone publish nothing. The changelog section is generated, the tag pushed, the multi-architecture image built, then main receives the release commit, the GitHub Release is created and a last job checks the public image, the store validator and the topic.
pr-title.yml checks it). Never edit CHANGELOG.md by hand.release-as: 1.0.0. dry-run shows the version and the notes without publishing.main with GITHUB_TOKEN. With a ruleset on main, add GitHub Actions to its bypass list (or push through a GitHub App), otherwise the publish job fails with instructions.ghcr.io package public (Package settings → Change visibility), or Gladys cannot pull it.See docs/en.md. Report issues with the versions of Gladys, of the integration and of Fail2Ban, and the lines of the Diagnostic button.
Issues and pull requests are welcome. Run npm run format:check && npm run lint && npm test before opening a pull request, and keep every external id and stored key unchanged (see CLAUDE.md).
See SECURITY.md: report vulnerabilities privately. The integration holds a door to your server, so it is built to keep it narrow: a dedicated user allowed to run fail2ban-client only, a key marked restrict, the host key checked, every argument validated and quoted, the password a secret field never logged, the private key in /data only, a read-only container as a non-root user.
The images above are illustrations, not screenshots. Real screenshots will go in docs/assets/screenshots/ (PNG, 1280 × 800): configuration.png, discovery.png, device.png, scene.png.
Apache License 2.0 — see also NOTICE. Fail2Ban is a separate project (GPL-2.0) that this integration drives through its command line, without including it. Thanks to the Gladys documentation and SDK, and to the Fail2Ban maintainers.