diff --git a/ChangeLog b/ChangeLog
index d744dba0..c5be981b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -58,6 +58,7 @@ ver. 0.10.6-dev (20??/??/??) - development edition
- `aggressive`: matches 401 and any variant (with and without username)
### New Features
+* new filter and jail for GitLab recognizing failed application logins (gh-2689)
### Enhancements
* introduced new prefix `{UNB}` for `datepattern` to disable word boundaries in regex;
diff --git a/config/filter.d/gitlab.conf b/config/filter.d/gitlab.conf
new file mode 100644
index 00000000..0c614ae5
--- /dev/null
+++ b/config/filter.d/gitlab.conf
@@ -0,0 +1,6 @@
+# Fail2Ban filter for Gitlab
+# Detecting unauthorized access to the Gitlab Web portal
+# typically logged in /var/log/gitlab/gitlab-rails/application.log
+
+[Definition]
+failregex = ^: Failed Login: username=.+ ip=$
diff --git a/config/jail.conf b/config/jail.conf
index bbf8740f..39ebbe6d 100644
--- a/config/jail.conf
+++ b/config/jail.conf
@@ -819,6 +819,10 @@ udpport = 1200,27000,27001,27002,27003,27004,27005,27006,27007,27008,27009,27010
action_ = %(default/action_)s[name=%(__name__)s-tcp, port="%(tcpport)s", protocol="tcp"]
%(default/action_)s[name=%(__name__)s-udp, port="%(udpport)s", protocol="udp"]
+[gitlab]
+port = http,https
+logpath = /var/log/gitlab/gitlab-rails/application.log
+
[bitwarden]
port = http,https
logpath = /home/*/bwdata/logs/identity/Identity/log.txt
diff --git a/fail2ban/tests/files/logs/gitlab b/fail2ban/tests/files/logs/gitlab
new file mode 100644
index 00000000..222df642
--- /dev/null
+++ b/fail2ban/tests/files/logs/gitlab
@@ -0,0 +1,5 @@
+# Access of unauthorized host in /var/log/gitlab/gitlab-rails/application.log
+# failJSON: { "time": "2020-04-09T14:04:00", "match": true , "host": "80.10.11.12" }
+2020-04-09T14:04:00.667Z: Failed Login: username=admin ip=80.10.11.12
+# failJSON: { "time": "2020-04-09T14:15:09", "match": true , "host": "80.10.11.12" }
+2020-04-09T14:15:09.344Z: Failed Login: username=user name ip=80.10.11.12