This Go application monitors specified services for login denial events and sends notifications via Gotify.
Find a file
2025-08-13 01:21:29 +08:00
data Create denynotify v1 2025-08-04 00:32:08 +08:00
.gitignore Create denynotify v1 2025-08-04 00:32:08 +08:00
config.example.json Add OpenObserve example 2025-08-13 01:21:29 +08:00
docker-compose.override.example.yml Create denynotify v1 2025-08-04 00:32:08 +08:00
docker-compose.yml Create denynotify v1 2025-08-04 00:32:08 +08:00
Dockerfile Create denynotify v1 2025-08-04 00:32:08 +08:00
go.mod Create denynotify v1 2025-08-04 00:32:08 +08:00
go.sum Create denynotify v1 2025-08-04 00:32:08 +08:00
main.go Create denynotify v1 2025-08-04 00:32:08 +08:00
README.md Add Windows OpenSSH Server example 2025-08-09 22:37:53 +08:00
screenshot.png Create denynotify v1 2025-08-04 00:32:08 +08:00

Deny Notify

Screenshot of a 'Login Denied on Nginx' error message. The error, timestamped 2025/08/04, indicates that the user 'admin' was not found during authentication. Technical details are also shown, including server request, host, and referrer information.

This Go application monitors specified services for login denial events and sends notifications via Gotify. This is best for internal networks or VPNs where there shouldn't be any incorrect login attempts, and incorrect login attempts may indicate a security breach or misconfiguration.

Features

  • Monitors plain text log files and Docker container logs.
  • Uses regex to filter relevant log lines.
  • Tracks processed entries to prevent duplicate notifications.
  • Example regex configs for several services, including NGINX.

Usage

Before running, ensure you have Docker and Docker Compose installed on your system.

  • Copy docker-compose.override.example.yml to docker-compose.override.yml.
  • Copy config.example.yml to config.yml.
  • Configure docker-compose.override.yml and config.yml according to your needs (see Configuration section below).
  • If you are using HTTPS for your Gotify server and you have a custom CA certificate, place your custom CA certificate in a file named ca.crt. If you don't need a custom CA certificate, create an empty ca.crt file.
  • Run the command: docker compose up -d --build.

Security Considerations

By default, the Docker socket is mounted into the container. Do not expose this container publicly or on an untrusted network, as any attackers with access to the internals of the container will have access to the host's Docker socket, which in turn will allow them to run arbitrary images and access any files as root (by binding mounts).

Configuration

config.json

The application reads configuration from config.json. Required settings include:

  • debug: Set to true if you want debug output.
  • gotifyUrl: The URL of your Gotify server.
  • gotifyApiKey: The API key used to authenticate with Gotify.
  • refreshInterval: The interval (in seconds) between checks.
  • services: A list of services you want to monitor.

There are currently two types of supported services: plain text logs and Docker logs.

Plain Text Logs

  • friendlyName: A friendly name used when sending notifications.
  • type: "log" in this case.
  • logFile: The path to your log file, in the container. Please remember to create bind mounts in docker-compose.override.yml.
  • tail: The number of lines from the end of your log file that will be checked. If 0 or -1, the entire log file will be checked.
  • regexId: A regular expression that matches an ID per line -- this is used to differentiate between the different lines and to prevent duplicate notifications. Usually, millisecond-based timestamps are good, but if no ID is possible, matching the entire line works too.
  • regexDeny: A regular expression that matches a line that should trigger a notification -- specifically, a line that indicates a failed login attempt.

Docker Logs

  • friendlyName: A friendly name used when sending notifications.
  • type: "log" in this case.
  • dockerContainer: The name or ID of your Docker container.
  • tail: The number of lines from the end of your log file that will be checked. If 0 or -1, the entire log file will be checked.
  • regexId: A regular expression that matches an ID per line -- this is used to differentiate between the different lines and to prevent duplicate notifications. Usually, millisecond-based timestamps are good, but if no ID is possible, matching the entire line works too.
  • regexDeny: A regular expression that matches a line that should trigger a notification -- specifically, a line that indicates a failed login attempt.

config.example.json

This file contains an example config, which also contains somewhat-tested regexes for several services. It's best practice to remove the services that you aren't using in your actual config file. Edit them if you need to, of course.

Example service regexes included are:

  • Nginx
  • LibreChat
  • Radicale
  • Actual
  • Gotify
  • Uptime Kuma
  • Windows OpenSSH Server

docker-compose.override.yml

This file is responsible for two things: exposing the healthcheck port if you require it, and mounting your log files into the container. Please remember that your in-container log file paths must be the same between the config file and your Docker Compose override file.

License

This is free and unencumbered software released into the public domain.

Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means.

In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

For more information, please refer to https://unlicense.org/