diff --git a/.codespellrc b/.codespellrc
new file mode 100644
index 00000000..ec686145
--- /dev/null
+++ b/.codespellrc
@@ -0,0 +1,12 @@
+[codespell]
+# THANKS - names
+skip = .git,*.pdf,*.svg,venv,.codespellrc,THANKS,*test*.log,logs
+check-hidden = true
+# Ignore all acronyms etc as plenty e.g. in fail2ban/server/strptime.py
+# Try to identify incomplete words which are part of a regex, hence having [] at the beginning
+# Ignore all urls as something with :// in it
+# Ignore all lines with codespell-ignore in them for pragma annotation
+ignore-regex = (\b([A-Z][A-Z][A-Z]+|gir\.st)\b)|\[[a-zA-Z]+\][a-z]+\b|[a-z]+://\S+|.*codespell-ignore.*
+# some oddly named variables, some names, etc
+# wee -- comes in regex etc for weeks
+ignore-words-list = theis,timere,alls,wee,wight,ans
diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml
new file mode 100644
index 00000000..7373affc
--- /dev/null
+++ b/.github/workflows/codespell.yml
@@ -0,0 +1,22 @@
+---
+name: Codespell
+
+on:
+  push:
+    branches: [master]
+  pull_request:
+    branches: [master]
+
+permissions:
+  contents: read
+
+jobs:
+  codespell:
+    name: Check for spelling errors
+    runs-on: ubuntu-latest
+
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v3
+      - name: Codespell
+        uses: codespell-project/actions-codespell@v2
diff --git a/ChangeLog b/ChangeLog
index 5d1e933b..99f34c51 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -74,7 +74,7 @@ ver. 1.0.1 (2022/09/27) - energy-equals-mass-times-the-speed-of-light-squared
 * [stability] solves race condition with uncontrolled growth of failure list (jail with too many matches,
   that did not cause ban), behavior changed to ban ASAP, gh-2945
 * fixes search for the best datepattern - e. g. if line is too short, boundaries check for previously known
-  unprecise pattern may fail on incomplete lines (logging break-off, no flush, etc), gh-3020
+  imprecise pattern may fail on incomplete lines (logging break-off, no flush, etc), gh-3020
 * [stability, performance] backend `systemd`:
   - fixes error "local variable 'line' referenced before assignment", introduced in 55d7d9e2, gh-3097
   - don't update database too often (every 10 ticks or ~ 10 seconds in production)
@@ -412,7 +412,7 @@ filter = flt[logtype=short]
 * `filter.d/znc-adminlog.conf`: new filter for ZNC (IRC bouncer); requires the adminlog module to be loaded
 
 ### Enhancements
-* introduced new options: `dbmaxmatches` (fail2ban.conf) and `maxmatches` (jail.conf) to contol
+* introduced new options: `dbmaxmatches` (fail2ban.conf) and `maxmatches` (jail.conf) to control
   how many matches per ticket fail2ban can hold in memory and store in database (gh-2402, gh-2118);
 * fail2ban.conf: introduced new section `[Thread]` and option `stacksize` to configure default size
   of the stack for threads running in fail2ban (gh-2356), it could be set in `fail2ban.local` to
@@ -522,7 +522,7 @@ ver. 0.10.3 (2018/04/04) - the-time-is-always-right-to-do-what-is-right
   - fixed root login refused regex (optional port before preauth, gh-2080);
   - avoid banning of legitimate users when pam_unix used in combination with other password method, so
     bypass pam_unix failures if accepted available for this user gh-2070;
-  - amend to gh-1263 with better handling of multiple attempts (failures for different user-names recognized immediatelly);
+  - amend to gh-1263 with better handling of multiple attempts (failures for different user-names recognized immediately);
   - mode `ddos` (and `aggressive`) extended to catch `Connection closed by ... [preauth]`, so in DDOS mode
     it counts failure on closing connection within preauth-stage (gh-2085);
 * `action.d/abuseipdb.conf`: fixed curl cypher errors and comment quote-issue (gh-2044, gh-2101);
@@ -852,7 +852,7 @@ ver. 0.10.0-alpha-1 (2016/07/14) - ipv6-support-etc
   sane environment in error case of `actioncheck`.
 * Reporting via abuseipdb.com:
   - Bans can now be reported to abuseipdb
-  - Catagories must be set in the config
+  - Categories must be set in the config
   - Relevant log lines included in report
 
 ### Enhancements
@@ -989,7 +989,7 @@ releases.
     - Rewritten without end-anchor ($), because of potential vulnerability on very long URLs.
 * filter.d/apache-badbots.conf - extended to recognize Jorgee Vulnerability Scanner (gh-1882)
 * filter.d/asterisk.conf
-    - fixed failregex AMI Asterisk authentification failed (see gh-1302)
+    - fixed failregex AMI Asterisk authentication failed (see gh-1302)
     - removed invalid (vulnerable) regex blocking IPs using forign data (from header "from")
       thus not the IP-address that really originates the request (see gh-1927)
     - fixed failregex for the SQL-injection attempts with single-quotes in connect-string (see gh-2011)
@@ -1289,7 +1289,7 @@ ver. 0.9.3 (2015/08/01) - lets-all-stay-friends
 * `filter.d/roundcube-auth.conf`
      - Updated regex to work with 'errors' log (1.0.5 and 1.1.1)
      - Added regex to work with 'userlogins' log
-* `action.d/sendmail*.conf` - use LC_ALL (superseeding LC_TIME) to override
+* `action.d/sendmail*.conf` - use LC_ALL (superseding LC_TIME) to override
   locale on systems with customized LC_ALL
 * performance fix: minimizes connection overhead, close socket only at
   communication end (gh-1099)
@@ -1459,7 +1459,7 @@ ver. 0.9.1 (2014/10/29) - better, faster, stronger
 * Ignored IPs are no longer banned when being restored from persistent
   database
 * Manually unbanned IPs are now removed from persistent database, such they
-  wont be banned again when Fail2Ban is restarted
+  won't be banned again when Fail2Ban is restarted
 * Pass "bantime" parameter to the actions in default jail's action
   definition(s)
 * `filters.d/sieve.conf` - fixed typo in _daemon.  Thanks Jisoo Park
@@ -1750,7 +1750,7 @@ those filters were used.
       all platforms to ensure permissions are the same before and after a ban.
       Closes gh-266. hostsdeny supports daemon_list now too.
     * `action.d/bsd-ipfw` - action option unused. Change blocktype to port unreach
-      instead of deny for consistancy.
+      instead of deny for consistency.
     * `filter.d/dovecot` - added to support different dovecot failure
       "..disallowed plaintext auth". Closes Debian bug #709324
     * `filter.d/roundcube-auth` - timezone offset can be positive or negative
@@ -1940,7 +1940,7 @@ fail2ban-users mailing list and IRC.
 ### New Features
 - Yaroslav Halchenko
     * [9ba27353] Add support for `jail.d/{confilefile}` and `fail2ban.d/{configfile}`
-      to provide additional flexibility to system adminstrators. Thanks to
+      to provide additional flexibility to system administrators. Thanks to
       beilber for the idea. Closes gh-114.
     * [3ce53e87] Add exim filter.
 - Erwan Ben Souiden
@@ -2091,7 +2091,7 @@ ver. 0.8.7 (2012/07/31) - stable
     * [47c03a2] files/nagios - spelling/grammar fixes
     * [b083038] updated Free Software Foundation's address
     * [9092a63] changed TLDs to invalid domains, in accordance with RFC 2606
-    * [642d9af,3282f86] reformated printing of jail's name to be consistent
+    * [642d9af,3282f86] reformatted printing of jail's name to be consistent
       with init's info messages
     * [3282f86] uniform use of capitalized Jail in the messages
 - Leonardo Chiquitto
@@ -2436,7 +2436,7 @@ ver. 0.6.1 (2006/03/16) - stable
 - Fixed crash when time format does not match data
 - Propagated patch from Debian to fix fail2ban search path addition to the path
   search list: now it is added first. Thanks to Nick Craig-Wood
-- Added SMTP authentification for mail notification. Thanks to Markus Hoffmann
+- Added SMTP authentication for mail notification. Thanks to Markus Hoffmann
 - Removed debug mode as it is confusing for people
 - Added parsing of timestamp in TAI64N format (#1275325). Thanks to Mark
   Edgington
@@ -2469,7 +2469,7 @@ ver. 0.5.5 (2005/10/26) - beta
     further adjusted by upstream author).
   * Added -f command line parameter for [findtime].
   * Added a cleanup of firewall rules on emergency shutdown when unknown
-    exception is catched.
+    exception is caught.
   * Fail2ban should not crash now if a wrong file name is specified in config.
   * reordered code a bit so that log targets are setup right after background
     and then only loglevel (verbose, debug) is processed, so the warning could
diff --git a/MANIFEST b/MANIFEST
index 6471df66..8c1d9f54 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -273,7 +273,7 @@ fail2ban/tests/files/config/apache-auth/noentry/.htaccess
 fail2ban/tests/files/config/apache-auth/README
 fail2ban/tests/files/database_v1.db
 fail2ban/tests/files/database_v2.db
-fail2ban/tests/files/filter.d/substition.conf
+fail2ban/tests/files/filter.d/substitution.conf
 fail2ban/tests/files/filter.d/testcase01.conf
 fail2ban/tests/files/filter.d/testcase02.conf
 fail2ban/tests/files/filter.d/testcase02.local
diff --git a/config/action.d/bsd-ipfw.conf b/config/action.d/bsd-ipfw.conf
index 444192d3..d0029454 100644
--- a/config/action.d/bsd-ipfw.conf
+++ b/config/action.d/bsd-ipfw.conf
@@ -80,7 +80,7 @@ block = ip
 # Option:  blocktype
 # Notes.:  How to block the traffic. Use a action from man 5 ipfw
 #          Common values: deny, unreach port, reset
-#          ACTION defination at the top of man ipfw for allowed values.
+#          ACTION definition at the top of man ipfw for allowed values.
 # Values:  STRING
 #
 blocktype = unreach port
diff --git a/config/action.d/cloudflare-token.conf b/config/action.d/cloudflare-token.conf
index 287621eb..ff5f5c4e 100644
--- a/config/action.d/cloudflare-token.conf
+++ b/config/action.d/cloudflare-token.conf
@@ -68,7 +68,7 @@ _cf_api_prms = -H "Authorization: Bearer <cftoken>" -H "Content-Type: applicatio
 
 # Declare your Cloudflare Authorization Bearer Token in the [DEFAULT] section of your jail.local file.
 
-# The Cloudflare <ZONE_ID> of hte domain you want to manage.
+# The Cloudflare <ZONE_ID> of the domain you want to manage.
 #
 # cfzone =
 
diff --git a/config/action.d/firewallcmd-ipset.conf b/config/action.d/firewallcmd-ipset.conf
index 15d22f9e..c5282c62 100644
--- a/config/action.d/firewallcmd-ipset.conf
+++ b/config/action.d/firewallcmd-ipset.conf
@@ -83,7 +83,7 @@ ipsettime = 0
 # Values: [ NUM ] Default: 65536
 maxelem = 65536
 
-# expresion to caclulate timeout from bantime, example:
+# expression to calculate timeout from bantime, example:
 # banaction = %(known/banaction)s[ipsettime='<timeout-bantime>']
 timeout-bantime = $([ "<bantime>" -le 2147483 ] && echo "<bantime>" || echo 0)
 
@@ -124,4 +124,4 @@ firewalld_familyopt = --option=family=inet6
 # DEV NOTES:
 #
 # Author: Edgar Hoch, Daniel Black, Sergey Brester and Mihail Politaev
-# firewallcmd-new / iptables-ipset-proto6 combined for maximium goodness
+# firewallcmd-new / iptables-ipset-proto6 combined for maximum goodness
diff --git a/config/action.d/iptables-ipset-proto4.conf b/config/action.d/iptables-ipset-proto4.conf
index d33008be..51648dbb 100644
--- a/config/action.d/iptables-ipset-proto4.conf
+++ b/config/action.d/iptables-ipset-proto4.conf
@@ -61,7 +61,7 @@ actionban = ipset --test f2b-<name> <ip> ||  ipset --add f2b-<name> <ip>
 #
 actionunban = ipset --test f2b-<name> <ip> && ipset --del f2b-<name> <ip>
 
-# Several capabilities used internaly:
+# Several capabilities used internally:
 
 rule-jump = -m set --match-set f2b-<name> src -j <blocktype>
 
diff --git a/config/action.d/iptables-ipset.conf b/config/action.d/iptables-ipset.conf
index 15aadd92..07f89415 100644
--- a/config/action.d/iptables-ipset.conf
+++ b/config/action.d/iptables-ipset.conf
@@ -59,7 +59,7 @@ actionban = ipset -exist add <ipmset> <ip> timeout <ipsettime>
 #
 actionunban = ipset -exist del <ipmset> <ip>
 
-# Several capabilities used internaly:
+# Several capabilities used internally:
 
 rule-jump = -m set --match-set <ipmset> src -j <blocktype>
 
@@ -82,7 +82,7 @@ ipsettime = 0
 # Values: [ NUM ] Default: 65536
 maxelem = 65536
 
-# expresion to caclulate timeout from bantime, example:
+# expression to calculate timeout from bantime, example:
 # banaction = %(known/banaction)s[ipsettime='<timeout-bantime>']
 timeout-bantime = $([ "<bantime>" -le 2147483 ] && echo "<bantime>" || echo 0)
 
diff --git a/config/action.d/iptables.conf b/config/action.d/iptables.conf
index 67d496f5..382716ac 100644
--- a/config/action.d/iptables.conf
+++ b/config/action.d/iptables.conf
@@ -62,7 +62,7 @@ pre-rule =
 
 rule-jump = -j <_ipt_rule_target>
 
-# Several capabilities used internaly:
+# Several capabilities used internally:
 
 _ipt_for_proto-iter = for proto in $(echo '<protocol>' | sed 's/,/ /g'); do
 _ipt_for_proto-done = done
diff --git a/config/action.d/ipthreat.conf b/config/action.d/ipthreat.conf
index 193a60f2..5a14fa3d 100644
--- a/config/action.d/ipthreat.conf
+++ b/config/action.d/ipthreat.conf
@@ -47,7 +47,7 @@
 # BadBot         256     Bad bot that is not honoring robots.txt or just flooding with too many requests, etc
 # Compromised    512     The ip has been taken over by malware or botnet
 # Phishing       1024    The ip is involved in phishing or spoofing
-# Iot            2048    The ip has targetted an iot (Internet of Things) device
+# Iot            2048    The ip has targeted an iot (Internet of Things) device
 # PortScan       4096    Port scan
 # See https://ipthreat.net/bulkreportformat for more information
 # ```
diff --git a/config/action.d/netscaler.conf b/config/action.d/netscaler.conf
index 87f7e7bf..0432031f 100644
--- a/config/action.d/netscaler.conf
+++ b/config/action.d/netscaler.conf
@@ -5,7 +5,7 @@
 # The script will add offender IPs to a dataset on netscaler, the dataset can then be used to block the IPs at a cs/vserver or global level
 # This dataset is then used to block IPs using responder policies on the netscaler.
 # 
-# The script assumes using HTTPS with unsecure certificate to access the netscaler, 
+# The script assumes using HTTPS with insecure certificate to access the netscaler, 
 # if you have a valid certificate installed remove the -k from the curl lines, or if you want http change it accordingly (and remove the -k)
 # 
 # This action depends on curl
diff --git a/config/action.d/nftables.conf b/config/action.d/nftables.conf
index 77cf3661..98f3c64e 100644
--- a/config/action.d/nftables.conf
+++ b/config/action.d/nftables.conf
@@ -44,7 +44,7 @@ match = <rule_match-<type>>
 #
 rule_stat = %(match)s <addr_family> saddr @<addr_set> <blocktype>
 
-# optional interator over protocol's:
+# optional iterator over protocol's:
 _nft_for_proto-custom-iter =
 _nft_for_proto-custom-done =
 _nft_for_proto-allports-iter =
diff --git a/config/action.d/shorewall-ipset-proto6.conf b/config/action.d/shorewall-ipset-proto6.conf
index 6f1e02d3..fade8107 100644
--- a/config/action.d/shorewall-ipset-proto6.conf
+++ b/config/action.d/shorewall-ipset-proto6.conf
@@ -88,7 +88,7 @@ default-ipsettime = 0
 # Values:  [ NUM ]  Default: 0 (managed by fail2ban by unban)
 ipsettime = 0
 
-# expresion to caclulate timeout from bantime, example:
+# expression to calculate timeout from bantime, example:
 # banaction = %(known/banaction)s[ipsettime='<timeout-bantime>']
 timeout-bantime = $([ "<bantime>" -le 2147483 ] && echo "<bantime>" || echo 0)
 
diff --git a/config/filter.d/apache-auth.conf b/config/filter.d/apache-auth.conf
index 40f6d6e3..e80ac9ac 100644
--- a/config/filter.d/apache-auth.conf
+++ b/config/filter.d/apache-auth.conf
@@ -64,7 +64,7 @@ ignoreregex =
 #     ^user .*: one-time-nonce mismatch - sending new nonce\s*$
 #     ^realm mismatch - got `(?:[^']*|.*?)' but no realm specified\s*$
 #
-# Because url/referer are foreign input, short form of regex used if long enough to idetify failure.
+# Because url/referer are foreign input, short form of regex used if long enough to identify failure.
 # 
 # Author: Cyril Jaquier
 # Major edits by Daniel Black and Ben Rubson.
diff --git a/config/filter.d/exim-spam.conf b/config/filter.d/exim-spam.conf
index 733c884b..1038cc0b 100644
--- a/config/filter.d/exim-spam.conf
+++ b/config/filter.d/exim-spam.conf
@@ -44,7 +44,7 @@ ignoreregex =
 honeypot = trap@example.com
 
 # DEV Notes:
-# The %(host_info) defination contains a <HOST> match
+# The %(host_info) definition contains a <HOST> match
 #
 # Author: Cyril Jaquier
 #         Daniel Black (rewrote with strong regexs)
diff --git a/config/filter.d/exim.conf b/config/filter.d/exim.conf
index 1f0c3d82..854c8ba7 100644
--- a/config/filter.d/exim.conf
+++ b/config/filter.d/exim.conf
@@ -43,10 +43,10 @@ mode = normal
 ignoreregex = 
 
 # DEV Notes:
-# The %(host_info) defination contains a <HOST> match
+# The %(host_info) definition contains a <HOST> match
 #
 # SMTP protocol synchronization error \([^)]*\)  <- This needs to be non-greedy
-# to void capture beyond ")" to avoid a DoS Injection vulnerabilty as input= is
+# to void capture beyond ")" to avoid a DoS Injection vulnerability as input= is
 # user injectable data.
 #
 # Author: Cyril Jaquier
diff --git a/config/filter.d/mongodb-auth.conf b/config/filter.d/mongodb-auth.conf
index 66c27abb..d02227e0 100644
--- a/config/filter.d/mongodb-auth.conf
+++ b/config/filter.d/mongodb-auth.conf
@@ -1,4 +1,4 @@
-# Fail2Ban filter for unsuccesfull MongoDB authentication attempts
+# Fail2Ban filter for unsuccessful MongoDB authentication attempts
 #
 # Logfile /var/log/mongodb/mongodb.log
 #
@@ -23,7 +23,7 @@ maxlines = 10
 #
 # Regarding the multiline regex:
 #
-# There can be a nunber of non-related lines between the first and second part
+# There can be a number of non-related lines between the first and second part
 # of this regex maxlines of 10 is quite generious.
 #
 # Note the capture __connid, includes the connection ID, used in second part of regex.
diff --git a/config/filter.d/mysqld-auth.conf b/config/filter.d/mysqld-auth.conf
index 421a26d5..4afd4ada 100644
--- a/config/filter.d/mysqld-auth.conf
+++ b/config/filter.d/mysqld-auth.conf
@@ -1,4 +1,4 @@
-# Fail2Ban filter for unsuccesful MySQL authentication attempts
+# Fail2Ban filter for unsuccessful MySQL authentication attempts
 #
 #
 # To log wrong MySQL access attempts add to /etc/my.cnf in [mysqld]:
diff --git a/config/filter.d/postfix.conf b/config/filter.d/postfix.conf
index b374f472..02c1aaba 100644
--- a/config/filter.d/postfix.conf
+++ b/config/filter.d/postfix.conf
@@ -17,7 +17,7 @@ _pref = [A-Z]{4}
 prefregex = ^%(__prefix_line)s<mdpr-<mode>> <F-CONTENT>.+</F-CONTENT>$
 
 # Extended RE for normal mode to match reject by unknown users or undeliverable address, can be set to empty to avoid this:
-exre-user = |[Uu](?:ser unknown|ndeliverable address)
+exre-user = |[Uu](?:ser unknown|ndeliverable address)  ; pragma: codespell-ignore
 
 mdpr-normal = (?:\w+: (?:milter-)?reject:|(?:improper command pipelining|too many errors) after \S+)
 mdre-normal=^%(_pref)s from [^[]*\[<HOST>\]%(_port)s: [45][50][04] [45]\.\d\.\d+ (?:(?:<[^>]*>)?: )?(?:(?:Helo command|(?:Sender|Recipient) address) rejected: )?(?:Service unavailable|(?:Client host|Command|Data command) rejected|Relay access denied|(?:Host|Domain) not found|need fully-qualified hostname|match%(exre-user)s)\b
diff --git a/config/filter.d/selinux-ssh.conf b/config/filter.d/selinux-ssh.conf
index 0e38eb11..f5aa9b08 100644
--- a/config/filter.d/selinux-ssh.conf
+++ b/config/filter.d/selinux-ssh.conf
@@ -21,7 +21,7 @@ _msg = (?:%(_anygrp)s )*acct=(?:"<F-USER>[^"]+</F-USER>"|<F-ALT_USER>\S+</F-ALT_
 
 # DEV Notes:
 #
-# Note: USER_LOGIN is ignored as this is the duplicate messsage
+# Note: USER_LOGIN is ignored as this is the duplicate message
 # ssh logs after 3 USER_AUTH failures.
 # 
 # Author: Daniel Black
diff --git a/config/filter.d/sogo-auth.conf b/config/filter.d/sogo-auth.conf
index 4155f89e..c01b0353 100644
--- a/config/filter.d/sogo-auth.conf
+++ b/config/filter.d/sogo-auth.conf
@@ -1,4 +1,4 @@
-# Fail2ban filter for SOGo authentcation
+# Fail2ban filter for SOGo authentication
 #
 # Log file usually in /var/log/sogo/sogo.log
 
diff --git a/config/filter.d/traefik-auth.conf b/config/filter.d/traefik-auth.conf
index 8022fee1..5be16909 100644
--- a/config/filter.d/traefik-auth.conf
+++ b/config/filter.d/traefik-auth.conf
@@ -5,7 +5,7 @@
 #
 # To use 'traefik-auth' filter you have to configure your Traefik instance to write
 # the access logs as describe in https://docs.traefik.io/configuration/logs/#access-logs
-# into a log file on host and specifiy users for Basic Authentication
+# into a log file on host and specify users for Basic Authentication
 # https://docs.traefik.io/configuration/entrypoints/#basic-authentication
 #
 # Example:
@@ -51,7 +51,7 @@
 
 [Definition]
 
-# Parameter "method" can be used to specifiy request method
+# Parameter "method" can be used to specify request method
 req-method = \S+
 # Usage example (for jail.local):
 #   filter = traefik-auth[req-method="GET|POST|HEAD"]
diff --git a/config/paths-common.conf b/config/paths-common.conf
index 4f6a5f71..ad9f6f28 100644
--- a/config/paths-common.conf
+++ b/config/paths-common.conf
@@ -67,7 +67,7 @@ proftpd_backend = %(default_backend)s
 pureftpd_log = %(syslog_ftp)s
 pureftpd_backend = %(default_backend)s
 
-# ftp, daemon and then local7 are tried at configure time however it is overwriteable at configure time
+# ftp, daemon and then local7 are tried at configure time however it is overwritable at configure time
 #
 wuftpd_log = %(syslog_ftp)s
 wuftpd_backend = %(default_backend)s
diff --git a/fail2ban/client/configreader.py b/fail2ban/client/configreader.py
index 8310ade1..6b65e71a 100644
--- a/fail2ban/client/configreader.py
+++ b/fail2ban/client/configreader.py
@@ -98,7 +98,7 @@ class ConfigReader():
 	def read(self, name, once=True):
 		""" Overloads a default (not shared) read of config reader.
 
-	  To prevent mutiple reads of config files with it includes, reads into 
+	  To prevent multiple reads of config files with it includes, reads into 
 	  the config reader, if it was not yet cached/shared by 'name'.
 	  """
 		# already shared ?
@@ -183,7 +183,7 @@ class ConfigReader():
 class ConfigReaderUnshared(SafeConfigParserWithIncludes):
 	"""Unshared config reader (previously ConfigReader).
 
-	Do not use this class (internal not shared/cached represenation).
+	Do not use this class (internal not shared/cached representation).
 	Use ConfigReader instead.
 	"""
 
diff --git a/fail2ban/client/fail2banregex.py b/fail2ban/client/fail2banregex.py
index aca262f0..22a96ebc 100644
--- a/fail2ban/client/fail2banregex.py
+++ b/fail2ban/client/fail2banregex.py
@@ -69,7 +69,7 @@ def debuggexURL(sample, regex, multiline=False, useDns="yes"):
 	if multiline: args['flags'] = 'm'
 	return 'https://www.debuggex.com/?' + urllib.parse.urlencode(args)
 
-def output(args): # pragma: no cover (overriden in test-cases)
+def output(args): # pragma: no cover (overridden in test-cases)
 	print(args)
 
 def shortstr(s, l=53):
@@ -280,7 +280,7 @@ class Fail2banRegex(object):
 			self._filter.setUseDns(opts.usedns)
 		self._filter.returnRawHost = opts.raw
 		self._filter.checkAllRegex = opts.checkAllRegex and not opts.out
-		# ignore pending (without ID/IP), added to matches if it hits later (if ID/IP can be retreved)
+		# ignore pending (without ID/IP), added to matches if it hits later (if ID/IP can be retrieved)
 		self._filter.ignorePending = bool(opts.out)
 		# callback to increment ignored RE's by index (during process):
 		self._filter.onIgnoreRegex = self._onIgnoreRegex
@@ -476,7 +476,7 @@ class Fail2banRegex(object):
 					ret.append(match)
 				else:
 					is_ignored = True
-			if self._opts.out: # (formated) output - don't need stats:
+			if self._opts.out: # (formatted) output - don't need stats:
 				return None, ret, None
 			# prefregex stats:
 			if self._filter.prefRegex:
@@ -595,7 +595,7 @@ class Fail2banRegex(object):
 					continue
 				line_datetimestripped, ret, is_ignored = self.testRegex(line)
 
-			if self._opts.out: # (formated) output:
+			if self._opts.out: # (formatted) output:
 				if len(ret) > 0 and not is_ignored: out(ret)
 				continue
 
diff --git a/fail2ban/client/fail2banserver.py b/fail2ban/client/fail2banserver.py
index eee78d5f..7e7f492d 100644
--- a/fail2ban/client/fail2banserver.py
+++ b/fail2ban/client/fail2banserver.py
@@ -45,7 +45,7 @@ class Fail2banServer(Fail2banCmdLine):
 
 	@staticmethod
 	def startServerDirect(conf, daemon=True, setServer=None):
-		logSys.debug("  direct starting of server in %s, deamon: %s", os.getpid(), daemon)
+		logSys.debug("  direct starting of server in %s, daemon: %s", os.getpid(), daemon)
 		from ..server.server import Server
 		server = None
 		try:
@@ -120,7 +120,7 @@ class Fail2banServer(Fail2banCmdLine):
 				if frk: # pragma: no cover
 					os.execv(exe, args)
 				else:
-					# use P_WAIT instead of P_NOWAIT (to prevent defunct-zomby process), it startet as daemon, so parent exit fast after fork):
+					# use P_WAIT instead of P_NOWAIT (to prevent defunct-zomby process), it started as daemon, so parent exit fast after fork):
 					ret = os.spawnv(os.P_WAIT, exe, args)
 					if ret != 0: # pragma: no cover
 						raise OSError(ret, "Unknown error by executing server %r with %r" % (args[1], exe))
diff --git a/fail2ban/client/jailreader.py b/fail2ban/client/jailreader.py
index 7c79ca48..d4ee3e8a 100644
--- a/fail2ban/client/jailreader.py
+++ b/fail2ban/client/jailreader.py
@@ -235,7 +235,7 @@ class JailReader(ConfigReader):
 		if e:
 			stream.extend([['config-error', "Jail '%s' skipped, because of wrong configuration: %s" % (self.__name, e)]])
 			return stream
-		# fill jail with filter options, using filter (only not overriden in jail):
+		# fill jail with filter options, using filter (only not overridden in jail):
 		if self.__filter:
 			stream.extend(self.__filter.convert())
 		# and using options from jail:
diff --git a/fail2ban/server/actions.py b/fail2ban/server/actions.py
index b052d342..65571c50 100644
--- a/fail2ban/server/actions.py
+++ b/fail2ban/server/actions.py
@@ -670,7 +670,7 @@ class Actions(JailThread, Mapping):
 					action.consistencyCheck(_beforeRepair)
 					continue
 			# fallback to single unbans:
-			logSys.debug("  Unban tickets each individualy")
+			logSys.debug("  Unban tickets each individually")
 			unbactions[name] = action
 		actions = unbactions
 		# flush the database also:
diff --git a/fail2ban/server/database.py b/fail2ban/server/database.py
index 17938063..294164c3 100644
--- a/fail2ban/server/database.py
+++ b/fail2ban/server/database.py
@@ -104,7 +104,7 @@ class Fail2BanDb(object):
 	sqlite3.OperationalError
 		Error connecting/creating a SQLite3 database.
 	RuntimeError
-		If exisiting database fails to update to new schema.
+		If existing database fails to update to new schema.
 
 	Attributes
 	----------
@@ -494,7 +494,7 @@ class Fail2BanDb(object):
 		Parameters
 		----------
 		jail : Jail
-			If specified, will only reutrn logs belonging to the jail.
+			If specified, will only return logs belonging to the jail.
 
 		Returns
 		-------
diff --git a/fail2ban/server/datetemplate.py b/fail2ban/server/datetemplate.py
index 518805bb..5dc721ae 100644
--- a/fail2ban/server/datetemplate.py
+++ b/fail2ban/server/datetemplate.py
@@ -357,7 +357,7 @@ class DatePatternRegex(DateTemplate):
 
 
 class DateTai64n(DateTemplate):
-	"""A date template which matches TAI64N formate timestamps.
+	"""A date template which matches TAI64N format timestamps.
 
 	Attributes
 	----------
diff --git a/fail2ban/server/failregex.py b/fail2ban/server/failregex.py
index f592b39f..85636f36 100644
--- a/fail2ban/server/failregex.py
+++ b/fail2ban/server/failregex.py
@@ -240,7 +240,7 @@ class Regex:
 	# Sets an internal cache (match object) in order to avoid searching for
 	# the pattern again. This method must be called before calling any other
 	# method of this object.
-	# @param a list of tupples. The tupples are ( prematch, datematch, postdatematch )
+	# @param a list of tuples. The tuples are ( prematch, datematch, postdatematch )
 	
 	def search(self, tupleLines, orgLines=None):
 		buf = tupleLines
diff --git a/fail2ban/server/filter.py b/fail2ban/server/filter.py
index 6fcb2aee..c2b4886b 100644
--- a/fail2ban/server/filter.py
+++ b/fail2ban/server/filter.py
@@ -635,7 +635,7 @@ class Filter(JailThread):
 				e = m.end(1)
 				m = line[s:e]
 				tupleLine = (line[:s], m, line[e:])
-				if m: # found and not empty - retrive date:
+				if m: # found and not empty - retrieve date:
 					date = self.dateDetector.getTime(m, timeMatch)
 					if date is not None:
 						# Lets get the time part
@@ -666,7 +666,7 @@ class Filter(JailThread):
 		if self.checkFindTime and date is not None:
 			# if in operation (modifications have been really found):
 			if self.inOperation:
-				# if weird date - we'd simulate now for timeing issue (too large deviation from now):
+				# if weird date - we'd simulate now for timing issue (too large deviation from now):
 				delta = int(date - MyTime.time())
 				if abs(delta) > 60:
 					# log timing issue as warning once per day:
diff --git a/fail2ban/server/filtersystemd.py b/fail2ban/server/filtersystemd.py
index 2ab67a9a..5ff1bff2 100644
--- a/fail2ban/server/filtersystemd.py
+++ b/fail2ban/server/filtersystemd.py
@@ -344,7 +344,7 @@ class FilterSystemd(JournalFilter): # pragma: systemd no cover
 							except OSError:
 								pass
 				if self.idle:
-					# because journal.wait will returns immediatelly if we have records in journal,
+					# because journal.wait will returns immediately if we have records in journal,
 					# just wait a little bit here for not idle, to prevent hi-load:
 					if not Utils.wait_for(lambda: not self.active or not self.idle, 
 						self.sleeptime * 10, self.sleeptime
@@ -434,7 +434,7 @@ class FilterSystemd(JournalFilter): # pragma: systemd no cover
 		return ret
 
 	def _updateDBPending(self):
-		"""Apply pending updates (jornal position) to database.
+		"""Apply pending updates (journal position) to database.
 		"""
 		db = self.jail.database
 		while True:
diff --git a/fail2ban/server/observer.py b/fail2ban/server/observer.py
index b1c9b37d..31858ecc 100644
--- a/fail2ban/server/observer.py
+++ b/fail2ban/server/observer.py
@@ -161,7 +161,7 @@ class ObserverThread(JailThread):
 		self.pulse_notify()
 
 	def add_wn(self, *event):
-		"""Add a event to queue withouth notifying thread to wake up.
+		"""Add a event to queue without notifying thread to wake up.
 		"""
 		## lock and add new event to queue:
 		with self._queue_lock:
@@ -465,7 +465,7 @@ class ObserverThread(JailThread):
 		return banTime
 
 	def banFound(self, ticket, jail, btime):
-		""" Notify observer a ban occured for ip
+		""" Notify observer a ban occurred for ip
 
 		Observer will check ip was known (bad) and possibly increase/prolong a ban time
 		Secondary we will actualize the bans and bips (bad ip) in database
@@ -507,7 +507,7 @@ class ObserverThread(JailThread):
 			logSys.error('%s', e, exc_info=logSys.getEffectiveLevel()<=logging.DEBUG)
 
 	def prolongBan(self, ticket, jail):
-		""" Notify observer a ban occured for ip
+		""" Notify observer a ban occurred for ip
 
 		Observer will check ip was known (bad) and possibly increase/prolong a ban time
 		Secondary we will actualize the bans and bips (bad ip) in database
@@ -521,7 +521,7 @@ class ObserverThread(JailThread):
 		except Exception as e:
 			logSys.error('%s', e, exc_info=logSys.getEffectiveLevel()<=logging.DEBUG)
 
-# Global observer initial created in server (could be later rewriten via singleton)
+# Global observer initial created in server (could be later rewritten via singleton)
 class _Observers:
 	def __init__(self):
 		self.Main = None
diff --git a/fail2ban/server/server.py b/fail2ban/server/server.py
index bdbe88ca..996ca633 100644
--- a/fail2ban/server/server.py
+++ b/fail2ban/server/server.py
@@ -222,7 +222,7 @@ class Server:
 			obsMain.stop()
 
 		# Explicit close database (server can leave in a thread, 
-		# so delayed GC can prevent commiting changes)
+		# so delayed GC can prevent committing changes)
 		if self.__db:
 			self.__db.close()
 			self.__db = None
diff --git a/fail2ban/server/strptime.py b/fail2ban/server/strptime.py
index 1f459f02..9b6b85df 100644
--- a/fail2ban/server/strptime.py
+++ b/fail2ban/server/strptime.py
@@ -60,7 +60,7 @@ timeRE['H'] = r"(?P<H>[0-1]?\d|2[0-3])"
 timeRE['M'] = r"(?P<M>[0-5]?\d)"
 timeRE['S'] = r"(?P<S>[0-5]?\d|6[0-1])"
 
-# Extend build-in TimeRE with some exact patterns
+# Extend built-in TimeRE with some exact patterns
 # exact two-digit patterns:
 timeRE['Exd'] = r"(?P<d>[1-2]\d|0[1-9]|3[0-1])"
 timeRE['Exm'] = r"(?P<m>0[1-9]|1[0-2])"
@@ -307,7 +307,7 @@ def reGroupDictStrptime(found_dict, msec=False, default_tz=None):
 		day = now.day
 		assume_today = True
 
-	# Actully create date
+	# Actually create date
 	date_result =  datetime.datetime(
 		year, month, day, hour, minute, second, fraction)
 	# Correct timezone if not supplied in the log linge
diff --git a/fail2ban/server/ticket.py b/fail2ban/server/ticket.py
index 80b1469c..72573ec4 100644
--- a/fail2ban/server/ticket.py
+++ b/fail2ban/server/ticket.py
@@ -257,7 +257,7 @@ class FailTicket(Ticket):
 		as estimation from rate by previous known interval (if it exceeds the findTime)
 		"""
 		if time > self._time:
-			# expand current interval and attemps count (considering maxTime):
+			# expand current interval and attempts count (considering maxTime):
 			if self._firstTime < time - maxTime:
 				# adjust retry calculated as estimation from rate by previous known interval:
 				self._retry = int(round(self._retry / float(time - self._firstTime) * maxTime))
diff --git a/fail2ban/tests/actiontestcase.py b/fail2ban/tests/actiontestcase.py
index 772c687f..c353376c 100644
--- a/fail2ban/tests/actiontestcase.py
+++ b/fail2ban/tests/actiontestcase.py
@@ -70,7 +70,7 @@ class CommandActionTest(LogCaptureTestCase):
 			lambda: substituteRecursiveTags({'A': '<B>', 'B': '<A>'}))
 		self.assertRaises(ValueError,
 			lambda: substituteRecursiveTags({'A': '<B>', 'B': '<C>', 'C': '<A>'}))
-		# Unresolveable substition
+		# Unresolveable substitution
 		self.assertRaises(ValueError,
 			lambda: substituteRecursiveTags({'A': 'to=<B> fromip=<IP>', 'C': '<B>', 'B': '<C>', 'D': ''}))
 		self.assertRaises(ValueError,
@@ -246,7 +246,7 @@ class CommandActionTest(LogCaptureTestCase):
 			lambda: self.__action.replaceTag("<a><b>", 
 				self.__action._properties, conditional="family=inet4")
 		)
-		# remore self-referencing in props:
+		# remote self-referencing in props:
 		delattr(self.__action, 'ac')
 		# produce self-referencing query except:
 		self.assertRaisesRegex(ValueError, r"possible self referencing definitions in query",
@@ -276,7 +276,7 @@ class CommandActionTest(LogCaptureTestCase):
 					conditional="family=inet6", cache=cache),
 				"Text 890-567 text 567 '567'")
 		self.assertTrue(len(cache) >= 3)
-		# set one parameter - internal properties and cache should be reseted:
+		# set one parameter - internal properties and cache should be reset:
 		setattr(self.__action, 'xyz', "000-<abc>")
 		self.assertEqual(len(cache), 0)
 		# test againg, should have 000 instead of 890:
diff --git a/fail2ban/tests/clientreadertestcase.py b/fail2ban/tests/clientreadertestcase.py
index a98f4e94..1baff568 100644
--- a/fail2ban/tests/clientreadertestcase.py
+++ b/fail2ban/tests/clientreadertestcase.py
@@ -337,7 +337,7 @@ class JailReaderTest(LogCaptureTestCase):
 		self.assertTrue(jail.getOptions())
 		self.assertTrue(jail.isEnabled())
 		stream = jail.convert()
-		# check filter options are overriden with values specified directly in jail:
+		# check filter options are overridden with values specified directly in jail:
 		# prefregex:
 		self.assertEqual([['set', 'sshd-override-flt-opts', 'prefregex', '^Test']],
 			[o for o in stream if len(o) > 2 and o[2] == 'prefregex'])
@@ -565,7 +565,7 @@ class FilterReaderTest(LogCaptureTestCase):
 
 	def testFilterReaderSubstitionDefault(self):
 		output = [['set', 'jailname', 'addfailregex', 'to=sweet@example.com fromip=<IP>']]
-		filterReader = FilterReader('substition', "jailname", {},
+		filterReader = FilterReader('substitution', "jailname", {},
 		  share_config=TEST_FILES_DIR_SHARE_CFG, basedir=TEST_FILES_DIR)
 		filterReader.read()
 		filterReader.getOptions(None)
@@ -585,7 +585,7 @@ class FilterReaderTest(LogCaptureTestCase):
 		
 	def testFilterReaderSubstitionSet(self):
 		output = [['set', 'jailname', 'addfailregex', 'to=sour@example.com fromip=<IP>']]
-		filterReader = FilterReader('substition', "jailname", {'honeypot': 'sour@example.com'},
+		filterReader = FilterReader('substitution', "jailname", {'honeypot': 'sour@example.com'},
 		  share_config=TEST_FILES_DIR_SHARE_CFG, basedir=TEST_FILES_DIR)
 		filterReader.read()
 		filterReader.getOptions(None)
@@ -595,8 +595,8 @@ class FilterReaderTest(LogCaptureTestCase):
 	def testFilterReaderSubstitionKnown(self):
 		output = [['set', 'jailname', 'addfailregex', '^to=test,sweet@example.com,test2,sweet@example.com fromip=<IP>$']]
 		filterName, filterOpt = extractOptions(
-			'substition[failregex="^<known/failregex>$", honeypot="<sweet>,<known/honeypot>", sweet="test,<known/honeypot>,test2"]')
-		filterReader = FilterReader('substition', "jailname", filterOpt,
+			'substitution[failregex="^<known/failregex>$", honeypot="<sweet>,<known/honeypot>", sweet="test,<known/honeypot>,test2"]')
+		filterReader = FilterReader('substitution', "jailname", filterOpt,
 		  share_config=TEST_FILES_DIR_SHARE_CFG, basedir=TEST_FILES_DIR)
 		filterReader.read()
 		filterReader.getOptions(None)
@@ -606,8 +606,8 @@ class FilterReaderTest(LogCaptureTestCase):
 	def testFilterReaderSubstitionSection(self):
 		output = [['set', 'jailname', 'addfailregex', '^\\s*to=fail2ban@localhost fromip=<IP>\\s*$']]
 		filterName, filterOpt = extractOptions(
-			'substition[failregex="^\\s*<Definition/failregex>\\s*$", honeypot="<default/honeypot>"]')
-		filterReader = FilterReader('substition', "jailname", filterOpt,
+			'substitution[failregex="^\\s*<Definition/failregex>\\s*$", honeypot="<default/honeypot>"]')
+		filterReader = FilterReader('substitution', "jailname", filterOpt,
 		  share_config=TEST_FILES_DIR_SHARE_CFG, basedir=TEST_FILES_DIR)
 		filterReader.read()
 		filterReader.getOptions(None)
@@ -616,13 +616,13 @@ class FilterReaderTest(LogCaptureTestCase):
 
 	def testFilterReaderSubstitionFail(self):
 		# directly subst the same var :
-		filterReader = FilterReader('substition', "jailname", {'honeypot': '<honeypot>'},
+		filterReader = FilterReader('substitution', "jailname", {'honeypot': '<honeypot>'},
 		  share_config=TEST_FILES_DIR_SHARE_CFG, basedir=TEST_FILES_DIR)
 		filterReader.read()
 		filterReader.getOptions(None)
 		self.assertRaises(ValueError, FilterReader.convert, filterReader)
 		# cross subst the same var :
-		filterReader = FilterReader('substition', "jailname", {'honeypot': '<sweet>', 'sweet': '<honeypot>'},
+		filterReader = FilterReader('substitution', "jailname", {'honeypot': '<sweet>', 'sweet': '<honeypot>'},
 		  share_config=TEST_FILES_DIR_SHARE_CFG, basedir=TEST_FILES_DIR)
 		filterReader.read()
 		filterReader.getOptions(None)
diff --git a/fail2ban/tests/databasetestcase.py b/fail2ban/tests/databasetestcase.py
index 6ac483c6..c54f7489 100644
--- a/fail2ban/tests/databasetestcase.py
+++ b/fail2ban/tests/databasetestcase.py
@@ -127,7 +127,7 @@ class DatabaseTest(LogCaptureTestCase):
 			self.pruneLog("[test-repair], next phase - file-size: %d" % truncSize)
 			shutil.copyfile(
 				os.path.join(TEST_FILES_DIR, 'database_v1.db'), self.dbFilename)
-			# produce currupt database:
+			# produce corrupt database:
 			f = os.open(self.dbFilename, os.O_RDWR)
 			os.ftruncate(f, truncSize)
 			os.close(f)
diff --git a/fail2ban/tests/fail2banclienttestcase.py b/fail2ban/tests/fail2banclienttestcase.py
index 9d3f382f..28b908cd 100644
--- a/fail2ban/tests/fail2banclienttestcase.py
+++ b/fail2ban/tests/fail2banclienttestcase.py
@@ -440,7 +440,7 @@ class Fail2banClientServerBase(LogCaptureTestCase):
 					)
 		except:  # pragma: no cover
 			if _inherited_log(startparams):
-				print(('=== Error by wait fot server, log: ===\n%s===' % self.getLog()))
+				print(('=== Error by wait for server, log: ===\n%s===' % self.getLog()))
 				self.pruneLog()
 			log = pjoin(tmp, "f2b.log")
 			if isfile(log):
@@ -859,8 +859,8 @@ class Fail2banServerTest(Fail2banClientServerBase):
 		# Very complicated test-case, that expected running server (foreground in thread).
 		#
 		# In this test-case, each phase is related from previous one, 
-		# so it cannot be splitted in multiple test cases.
-		# Additionaly many log-messages used as ready-sign (to wait for end of phase).
+		# so it cannot be split in multiple test cases.
+		# Additionally many log-messages used as ready-sign (to wait for end of phase).
 		#
 		# Used file database (instead of :memory:), to restore bans and log-file positions,
 		# after restart/reload between phases.
diff --git a/fail2ban/tests/fail2banregextestcase.py b/fail2ban/tests/fail2banregextestcase.py
index f3db9e7f..685aa3b0 100644
--- a/fail2ban/tests/fail2banregextestcase.py
+++ b/fail2ban/tests/fail2banregextestcase.py
@@ -552,7 +552,7 @@ class Fail2banRegexTest(LogCaptureTestCase):
 		self.assertNotLogged('failure from == 192.0.2.4 ==')
 
 	def testWrongFilterFile(self):
-		# use test log as filter file to cover eror cases...
+		# use test log as filter file to cover error cases...
 		self.assertFalse(_test_exec(
 			FILENAME_ZZZ_GEN, FILENAME_ZZZ_GEN
 		))
diff --git a/fail2ban/tests/files/filter.d/substition.conf b/fail2ban/tests/files/filter.d/substitution.conf
similarity index 100%
rename from fail2ban/tests/files/filter.d/substition.conf
rename to fail2ban/tests/files/filter.d/substitution.conf
diff --git a/fail2ban/tests/filtertestcase.py b/fail2ban/tests/filtertestcase.py
index ea826479..8027846e 100644
--- a/fail2ban/tests/filtertestcase.py
+++ b/fail2ban/tests/filtertestcase.py
@@ -768,7 +768,7 @@ class LogFileFilterPoll(unittest.TestCase):
 			fc.setPos(0); self.filter.seekToTime(fc, time)
 			self.assertEqual(fc.getPos(), 157)
 
-			# stil one exact line:
+			# still one exact line:
 			f.write(b"%s [sshd] error: PAM: Authentication failure\n" % _tmb(time))
 			f.write(b"%s [sshd] error: PAM: failure len 1\n" % _tmb(time))
 			f.flush()
@@ -1056,7 +1056,7 @@ class CommonMonitorTestCase(unittest.TestCase):
 		return Utils.wait_for(lambda: self.filter.ticks >= last_ticks + ticks, _maxWaitTime(delay))
 
 	def commonFltError(self, reason="common", exc=None):
-		""" Mock-up for default common error handler to find catched unhandled exceptions
+		""" Mock-up for default common error handler to find caught unhandled exceptions
 		could occur in filters
 		"""
 		self._commonFltError(reason, exc)
@@ -1087,7 +1087,7 @@ def get_monitor_failures_testcase(Filter_):
 			self.file = open(self.name, 'ab')
 			self.jail = DummyJail()
 			self.filter = Filter_(self.jail)
-			# mock-up common error to find catched unhandled exceptions:
+			# mock-up common error to find caught unhandled exceptions:
 			self._commonFltError, self.filter.commonError = self.filter.commonError, self.commonFltError
 			self.filter.addLogPath(self.name, autoSeek=False)
 			# speedup search using exact date pattern:
@@ -1388,7 +1388,7 @@ def get_monitor_failures_journal_testcase(Filter_): # pragma: systemd no cover
 		def _initFilter(self, **kwargs):
 			self._getRuntimeJournal() # check journal available
 			self.filter = Filter_(self.jail, **kwargs)
-			# mock-up common error to find catched unhandled exceptions:
+			# mock-up common error to find caught unhandled exceptions:
 			self._commonFltError, self.filter.commonError = self.filter.commonError, self.commonFltError
 			self.filter.addJournalMatch([
 				"SYSLOG_IDENTIFIER=fail2ban-testcases",
@@ -1704,7 +1704,7 @@ class GetFailures(LogCaptureTestCase):
 		self.assertSortedEqual(self.filter.getLogPaths(), [GetFailures.FILENAME_01, GetFailures.FILENAME_02])
 
 	def testTail(self):
-		# There must be no containters registered, otherwise [-1] indexing would be wrong
+		# There must be no containers registered, otherwise [-1] indexing would be wrong
 		self.assertEqual(self.filter.getLogs(), [])
 		self.filter.addLogPath(GetFailures.FILENAME_01, tail=True)
 		self.assertEqual(self.filter.getLogs()[-1].getPos(), 1653)
@@ -2043,7 +2043,7 @@ class DNSUtilsTests(unittest.TestCase):
 			c.set(i, 1)
 		st = time.time()
 		self.assertTrue(Utils.wait_for(lambda: time.time() >= st + 0.0005, 1))
-		# we have still 5 elements (or fewer if too slow test mashine):
+		# we have still 5 elements (or fewer if too slow test machine):
 		self.assertTrue(len(c) <= 5)
 		# but all that are expiered also:
 		for i in range(10):
diff --git a/fail2ban/tests/misctestcase.py b/fail2ban/tests/misctestcase.py
index b0e29fb0..43fe35a8 100644
--- a/fail2ban/tests/misctestcase.py
+++ b/fail2ban/tests/misctestcase.py
@@ -205,19 +205,19 @@ class TestsUtilsTest(LogCaptureTestCase):
 				self.err = err
 			def __repr__(self):
 				if self.err:
-					raise Exception('no represenation for test!')
+					raise Exception('no representation for test!')
 				else:
 					return 'conv-error (\xf2\xf0\xe5\xf2\xe8\xe9), unterminated utf \xcf'
 		test = Test()
 		logSys.log(logging.NOTICE, "test 1a: %r", test)
-		self.assertLogged("Traceback", "no represenation for test!")
+		self.assertLogged("Traceback", "no representation for test!")
 		self.pruneLog()
 		logSys.notice("test 1b: %r", test)
-		self.assertLogged("Traceback", "no represenation for test!")
+		self.assertLogged("Traceback", "no representation for test!")
 
 		self.pruneLog('[phase 2] test error conversion by encoding %s' % sys.getdefaultencoding())
 		test = Test(0)
-		# this may produce coversion error on ascii default encoding:
+		# this may produce conversion error on ascii default encoding:
 		#str(test)
 		logSys.log(logging.NOTICE, "test 2a: %r, %s", test, test)
 		self.assertLogged("test 2a", "Error by logging handler", all=False)
diff --git a/fail2ban/tests/observertestcase.py b/fail2ban/tests/observertestcase.py
index ace1184c..d4a46a5b 100644
--- a/fail2ban/tests/observertestcase.py
+++ b/fail2ban/tests/observertestcase.py
@@ -104,7 +104,7 @@ class BanTimeIncr(LogCaptureTestCase):
 			[1200, 2400, 4800, 9600, 19200, 38400, 43200, 43200, 43200, 43200]
 		)
 		a.setBanTimeExtra('maxtime', '24h')
-		## test randomization - not possibe all 10 times we have random = 0:
+		## test randomization - not possible all 10 times we have random = 0:
 		a.setBanTimeExtra('rndtime', '5m')
 		self.assertTrue(
 			False in [1200 in [a.calcBanTime(600, 1) for i in range(10)] for c in range(10)]
@@ -159,7 +159,7 @@ class BanTimeIncr(LogCaptureTestCase):
 			[1200, 2400, 4800, 9600, 19200, 38400, 43200, 43200, 43200, 43200]
 		)
 		a.setBanTimeExtra('maxtime', '24h')
-		## test randomization - not possibe all 10 times we have random = 0:
+		## test randomization - not possible all 10 times we have random = 0:
 		a.setBanTimeExtra('rndtime', '5m')
 		self.assertTrue(
 			False in [1200 in [int(a.calcBanTime(600, 1)) for i in range(10)] for c in range(10)]
@@ -474,7 +474,7 @@ class BanTimeIncrDB(LogCaptureTestCase):
 		obs.wait_empty(5)
 
 		stime = int(MyTime.time())
-		# completelly empty ?
+		# completely empty ?
 		tickets = self.db.getBans()
 		self.assertEqual(tickets, [])
 
@@ -503,7 +503,7 @@ class BanTimeIncrDB(LogCaptureTestCase):
 		failManager.addFailure(ticket)
 		obs.add('failureFound', jail, ticket)
 		obs.wait_empty(5)
-		# wait until ticket transfered from failmanager into jail:
+		# wait until ticket transferred from failmanager into jail:
 		ticket2 = Utils.wait_for(jail.getFailTicket, 10)
 		# check ticket and failure count:
 		self.assertTrue(ticket2)
diff --git a/fail2ban/tests/servertestcase.py b/fail2ban/tests/servertestcase.py
index 695c80ee..c33eaf39 100644
--- a/fail2ban/tests/servertestcase.py
+++ b/fail2ban/tests/servertestcase.py
@@ -1301,7 +1301,7 @@ class ServerConfigReaderTests(LogCaptureTestCase):
 		# for j in jails:
 		# 	print(j, jails[j])
 
-		# test default stock actions sepecified in all stock jails:
+		# test default stock actions specified in all stock jails:
 		if not unittest.F2B.fast:
 			self._testExecActions(server)
 
@@ -1330,7 +1330,7 @@ class ServerConfigReaderTests(LogCaptureTestCase):
 
 		for actCfg in glob.glob(os.path.join(CONFIG_DIR, 'action.d', '*.conf')):
 			act = os.path.basename(actCfg).replace('.conf', '')
-			# transmit artifical jail with each action to the server:
+			# transmit artificial jail with each action to the server:
 			stream = self.getDefaultJailStream('j-'+act, act)
 			for cmd in stream:
 				# command to server:
diff --git a/fail2ban/tests/sockettestcase.py b/fail2ban/tests/sockettestcase.py
index 15253ce0..4eb3a375 100644
--- a/fail2ban/tests/sockettestcase.py
+++ b/fail2ban/tests/sockettestcase.py
@@ -230,7 +230,7 @@ class ClientMisc(LogCaptureTestCase):
 		def _poll(*args):
 			phase['cntr'] += 1
 			raise Exception('test *%d*' % phase['cntr'])
-		# test errors "catched" and logged:
+		# test errors "caught" and logged:
 		loop(_active, use_poll=_poll)
 		self.assertLogged("test *1*", "test *10*", "test *20*", all=True)
 		self.assertLogged("Too many errors - stop logging connection errors")
diff --git a/fail2ban/tests/tickettestcase.py b/fail2ban/tests/tickettestcase.py
index 771d2b50..6b250548 100644
--- a/fail2ban/tests/tickettestcase.py
+++ b/fail2ban/tests/tickettestcase.py
@@ -154,12 +154,12 @@ class TicketTests(unittest.TestCase):
     self.assertEqual(
       t.getData(), 
       {'matches': ['first', 'second'], 'failures':0, 'region': 'Hamburg', 'country': 'DE', 'city': 'Hamburg'})
-    # at once as dict (single argument, overwrites it completelly, no more matches/failures) :
+    # at once as dict (single argument, overwrites it completely, no more matches/failures) :
     t.setData({'region': None, 'country': 'FR', 'city': 'Paris'},)
     self.assertEqual(
       t.getData(), 
       {'city': 'Paris', 'country': 'FR'})
-    # at once as dict (overwrites it completelly, no more matches/failures) :
+    # at once as dict (overwrites it completely, no more matches/failures) :
     t.setData({'region': 'Hamburg', 'country': 'DE', 'city': None})
     self.assertEqual(
       t.getData(), 
@@ -185,7 +185,7 @@ class TicketTests(unittest.TestCase):
     self.assertEqual(
       t.getData(), 
       {'city':'Berlin', 'region': 'Brandenburg', 'country': 'DE'})
-    # interator filter :
+    # iterator filter :
     self.assertEqual(
       t.getData(('city', 'country')), 
       {'city':'Berlin', 'country': 'DE'})
diff --git a/fail2ban/tests/utils.py b/fail2ban/tests/utils.py
index ee967793..1d01d845 100644
--- a/fail2ban/tests/utils.py
+++ b/fail2ban/tests/utils.py
@@ -267,7 +267,7 @@ def initTests(opts):
 			raise unittest.SkipTest('Skip test because of "--fast"')
 		unittest.F2B.SkipIfFast = F2B_SkipIfFast
 	else:
-		# smaller inertance inside test-cases (litle speedup):
+		# smaller inertance inside test-cases (little speedup):
 		Utils.DEFAULT_SLEEP_TIME = 0.025
 		Utils.DEFAULT_SLEEP_INTERVAL = 0.005
 		Utils.DEFAULT_SHORT_INTERVAL = 0.0005
diff --git a/files/fail2ban-openrc.conf b/files/fail2ban-openrc.conf
index 9454ef68..57706d3d 100644
--- a/files/fail2ban-openrc.conf
+++ b/files/fail2ban-openrc.conf
@@ -1,2 +1,2 @@
-# For available options, plase run "fail2ban-server --help".
+# For available options, please run "fail2ban-server --help".
 #FAIL2BAN_OPTIONS="-x"
diff --git a/files/gen_badbots b/files/gen_badbots
index 75a6a0d5..9c450bca 100755
--- a/files/gen_badbots
+++ b/files/gen_badbots
@@ -8,7 +8,7 @@
 # DESCRIPTION (NOTES):
 #
 # Script to fetch list of agent strings from http://www.user-agents.org
-# which are known to be from mailicious bots, and create apache-badbots.conf
+# which are known to be from malicious bots, and create apache-badbots.conf
 # filter for fail2ban
 #
 # COPYRIGHT: Yaroslav Halchenko 2007-2013