By Manny Fernandez

October 11, 2026

Logcheck on Linux: How to Install It, Configure It, and Run It

Executive Summary

Objective: Deploy logcheck on a Debian or Ubuntu server so that every hour it reads the new log lines, throws away the ones you have declared boring, and emails you whatever is left.

Target audience: Linux admins and security practitioners who want log review on a single host or a small fleet without standing up a SIEM.

Logcheck works backwards from most log tools. It does not hunt for known bad strings and stay quiet otherwise. It assumes every line is interesting until a rule says it is not. That makes it noisy on day one and very useful by week two, because anything new on the box shows up in your inbox by default.

How Logcheck Thinks

Each run pulls only the lines written since the last run (tracked with logtail2 offsets in /var/lib/logcheck), then sorts them through three layers in order.

Layer Match directory Filter directory Mail subject
1. Attack alerts cracking.d cracking.ignore.d (off by default) Security Alerts
2. Security events violations.d violations.ignore.d Security Events
3. Everything else (all remaining lines) ignore.d.<level> System Events

The report level decides which ignore.d directories apply to layer 3. Levels are cumulative.

Level Ignore directories applied Result
paranoid ignore.d.paranoid Most mail. For hosts running very few services.
server paranoid + ignore.d.server The default. Right for most servers.
workstation paranoid + server + ignore.d.workstation Least mail. For desktops and laptops.

Prerequisites and Architecture

Assumed knowledge

  • Comfortable with sudo, apt, and editing files under /etc.
  • Basic extended regular expressions (the grep -E flavor).
  • A working idea of where your distribution writes logs: rsyslog files, the systemd journal, or both.

Lab environment

Component Value used in this guide Notes
Host log01 (10.0.10.20) Debian 12/13 or Ubuntu 22.04/24.04. On Ubuntu the package is in universe.
logcheck 1.4.x Check yours with logcheck -v. Journal support needs 1.4 or later.
Mail relay [mail.example.com]:587 Placeholder. Any MTA that can deliver local mail off the box works.
Report recipient secops@example.com Placeholder. Use a mailbox someone reads.
Scheduler /etc/cron.d/logcheck Shipped by the Debian package. Runs as user logcheck.

Note: This guide targets the Debian family, where logcheck is maintained. RHEL family distributions generally do not package it in the base repos, so check your repos before planning around it there.

Step-by-Step Implementation

Step 1: Install logcheck

Goal: Get the engine, the stock rule database, and the log tail helper on the box.

Action: Install the three packages. logcheck-database carries the stock rules and logtail provides logtail2.

sudo apt update
sudo apt install -y logcheck logcheck-database logtail

Verify: Confirm the version, the service account, and its group membership. The logcheck user must be in adm to read /var/log and the journal.

logcheck -v
id logcheck
ls -ld /etc/logcheck /var/lib/logcheck

Step 2: Make sure the host can send mail

Goal: Logcheck hands its report to the local mail command. No MTA means no reports, and it fails quietly.

Action: If the host has no MTA yet, install Postfix as a loopback-only relay client and a mail binary. Replace the relay with your own. If your relay needs authentication, add the usual SASL settings.

sudo apt install -y postfix bsd-mailx
sudo postconf -e 'relayhost = [mail.example.com]:587'
sudo postconf -e 'inet_interfaces = loopback-only'
sudo systemctl restart postfix

Verify: Send a test message and watch it leave the queue.

echo "mail path test from log01" | mail -s "log01 test" secops@example.com
mailq
sudo journalctl -u postfix --since -5min --no-pager | tail

Step 3: Set the core options in logcheck.conf

Goal: Pick the report level and tell logcheck where to send mail.

Action: Edit /etc/logcheck/logcheck.conf. These are the settings that matter on day one.

sudo nano /etc/logcheck/logcheck.conf
# paranoid | server | workstation
REPORTLEVEL="server"

# Where reports go. Default is the local "logcheck" user.
SENDMAILTO="secops@example.com"

# 1 = send the report as an attachment instead of inline
MAILASATTACH=0

# 1 = use the fully qualified hostname in the subject
FQDN=1

# 1 = collapse identical lines (sort -u) to shrink reports
SORTUNIQ=0

# 1 = let cracking.ignore.d filter the Security Alerts layer
SUPPORT_CRACKING_IGNORE=0

# Optional tag added to every subject line, handy for mail filters
ADDTAG="no"
Setting What it does Recommendation
REPORTLEVEL Selects which ignore.d directories apply. Start at server.
SENDMAILTO Report recipient. Local user or full address. A shared mailbox, not one person.
MAILASATTACH Inline body versus attachment. Leave at 0 so you can skim on a phone.
FQDN Short or full hostname in the subject. 1 if you run more than a few hosts.
SORTUNIQ Deduplicates identical lines. 0 at first. You lose ordering and counts at 1.
SUPPORT_CRACKING_IGNORE Allows ignoring attack alerts. Leave at 0 unless a stock rule misfires.

Verify: List the active (uncommented) settings.

sudo grep -Ev '^\s*(#|$)' /etc/logcheck/logcheck.conf

Step 4: Tell logcheck which logs to read

Goal: Point logcheck at the right sources. This is where most silent failures come from.

Action: Sources are listed one per line in /etc/logcheck/logcheck.logfiles and in any *.logfiles file under /etc/logcheck/logcheck.logfiles.d/. Version 1.4 ships two drop-ins.

ls -l /etc/logcheck/logcheck.logfiles.d/
cat /etc/logcheck/logcheck.logfiles.d/journal.logfiles
cat /etc/logcheck/logcheck.logfiles.d/syslog.logfiles
File Contents When it matters
journal.logfiles The keyword journal Hosts with no rsyslog, such as a default Debian 12 or later install.
syslog.logfiles /var/log/syslog and /var/log/auth.log Hosts running rsyslog, such as Ubuntu Server.

If the host runs both the journal and rsyslog, you will see every event twice. Pick one source and comment out the other. Then add any application logs you care about in your own drop-in.

# Example: rsyslog host, so stop reading the journal too
sudo sed -i 's/^journal/#journal/' \
  /etc/logcheck/logcheck.logfiles.d/journal.logfiles

# Example: add application logs
sudo tee /etc/logcheck/logcheck.logfiles.d/local.logfiles <<'EOF'
/var/log/nginx/error.log
/var/log/fail2ban.log
EOF
sudo chown root:logcheck /etc/logcheck/logcheck.logfiles.d/local.logfiles
sudo chmod 640 /etc/logcheck/logcheck.logfiles.d/local.logfiles

Verify: Confirm the logcheck user can actually read each file you listed.

sudo -u logcheck head -n 1 /var/log/nginx/error.log
sudo -u logcheck journalctl -n 1 --no-pager

Step 5: Run it by hand

Goal: See a report on screen before any mail is sent, and without moving the log offsets.

Action: Always run as the logcheck user, never as root. -o prints to stdout instead of mailing. -t is test mode, so offsets are not updated and you can rerun against the same lines.

sudo -u logcheck logcheck -o -t

Expect a large first report. Logcheck has never run, so everything in the current logs is new. When you are ready, do one real run to send the first mail and set the offsets.

sudo -u logcheck logcheck

Verify: Offsets now exist in the state directory.

sudo ls -l /var/lib/logcheck/

Step 6: Tune it with local ignore rules

Goal: Turn the report from a wall of text into a short list of things worth reading. This step is the real work and it never fully ends.

Action: Rules are extended regular expressions, one per line, matched against the whole log line. Put your own rules in a new file under the directory for your level. Never edit the stock files, because package upgrades replace them.

Stock rules start with a prefix that matches the timestamp and hostname. The 1.4 form handles both the classic syslog timestamp and the ISO timestamp:

^(\w{3} [ :[:digit:]]{11}|[0-9T:.+-]{32}) [._[:alnum:]-]+

Generate a test event, confirm logcheck reports it, then write a rule to silence it.

logger -t mtest "probe 001"
sudo -u logcheck logcheck -o -t | grep mtest
sudo nano /etc/logcheck/ignore.d.server/local-mtest
^(\w{3} [ :[:digit:]]{11}|[0-9T:.+-]{32}) [._[:alnum:]-]+ mtest: probe [0-9]+$
sudo chown root:logcheck /etc/logcheck/ignore.d.server/local-mtest
sudo chmod 640 /etc/logcheck/ignore.d.server/local-mtest

Three rules for rule files, all of which fail silently if you break them:

  • No dots in the filename. Logcheck loads rule files the way run-parts does, so local-mtest loads and local-mtest.rules is skipped.
  • Readable by the logcheck group. A root-only file is skipped.
  • Be specific. Anchor with ^ and $ and match variable parts with tight classes like [0-9]+. A lazy .* rule will one day hide the line you needed to see.

To silence a line that shows up under Security Events, the rule goes in violations.ignore.d instead. An ignore.d rule has no effect on that layer.

Verify: Rerun in test mode. The count should be 0.

sudo -u logcheck logcheck -o -t | grep -c mtest

Note: On rsyslog hosts you can also test a rule file directly against a log with grep -E -f <rulefile> /var/log/syslog. Any line it prints is a line the rule would suppress.

Step 7: Schedule it

Goal: Hands-off hourly reports.

Action: On Debian and Ubuntu the package already did this. Review the cron file and adjust the interval if hourly is not what you want.

cat /etc/cron.d/logcheck
@reboot    logcheck  if [ -x /usr/sbin/logcheck ]; then \
                       nice -n10 /usr/sbin/logcheck -R; fi
2 * * * *  logcheck  if [ -x /usr/sbin/logcheck ]; then \
                       nice -n10 /usr/sbin/logcheck; fi

The first entry sends a report after every reboot (-R marks the subject as a reboot run). The second runs at minute 2 of every hour. Your file may be formatted slightly differently, and each entry is a single line in the real file. For a quieter cadence, change 2 * * * * to something like 2 */4 * * *.

Verify: Confirm cron is firing the job.

sudo journalctl -u cron --since -2h --no-pager | grep -i logcheck

Verification and Validation

Run this end-to-end test once the tuning rule from Step 6 is in place. It proves the full path: log source, rule engine, mail.

# 1. A line that no rule ignores
logger -t monkeycheck "unrecognized event $(date +%s)"

# 2. A real run (updates offsets, sends mail)
sudo -u logcheck logcheck

# 3. Confirm the MTA accepted and relayed it
sudo journalctl -u postfix --since -5min --no-pager | grep status=

Success looks like this:

  • Postfix logs status=sent for a message to your report address.
  • A mail arrives with a subject like log01 2026-10-01 14:02 System Events.
  • The body lists the monkeycheck line under System Events and does not list the mtest line.
  • A second run with no new log lines sends nothing. No mail is the normal healthy state.

Troubleshooting and Gotchas

1. No mail ever arrives

Work the path from the left. Does logcheck produce a report, and does the MTA deliver it?

sudo -u logcheck logcheck -o -t | head -n 40
sudo -u logcheck logcheck -d 2>&1 | tail -n 40
mailq
sudo journalctl -u postfix --since -1h --no-pager | tail -n 20

Resolution: If -o -t prints a report but nothing is delivered, the problem is mail: missing mail binary, no MTA, or the relay is rejecting you. If SENDMAILTO is still the default logcheck, the report is going to a local alias (usually root), so check /etc/aliases or set a real address.

2. Reports are empty or logcheck complains it cannot read a file

Either the source list does not match how this host logs, or the logcheck user lacks read access.

systemctl is-active rsyslog
ls -l /var/log/syslog /var/log/auth.log
id logcheck
sudo -u logcheck journalctl -n 3 --no-pager

Resolution: No rsyslog means the files in syslog.logfiles do not exist, so make sure the journal line is active. For permission errors, add the user back to the group with sudo usermod -aG adm logcheck. Also remember that running logcheck as root is refused by design.

3. A custom rule does nothing

In order of likelihood: the filename has a dot, the file is not group readable, the rule is in the wrong directory for the layer, or the regex does not match the whole line (trailing whitespace is a classic).

ls -l /etc/logcheck/ignore.d.server/ | grep local
sudo -u logcheck cat /etc/logcheck/ignore.d.server/local-mtest
grep -n ' $' /etc/logcheck/ignore.d.server/local-mtest

Resolution: Rename without dots, set root:logcheck and mode 640, and copy the exact line from the report when building the regex. If the line is reported under Security Events, move the rule to violations.ignore.d.

4. Every event appears twice

Resolution: The host logs to both the journal and rsyslog and both sources are active. Comment out one of them as shown in Step 4.

Quick Reference

Flag Meaning
-o Print the report to stdout instead of mailing it.
-t Test mode. Do not update log offsets.
-d Debug output.
-p / -s / -w Force report level paranoid, server, or workstation for this run.
-m <addr> Override the mail recipient for this run.
-l <file> Check one extra log file.
-L <file> Use an alternate logfiles list.
-c <file> Use an alternate config file.
-r <dir> Use an alternate rule directory.
-u Unique sort the output for this run.
-R Reboot run. Tags the mail subject accordingly.
-v Print the version.
Path Purpose
/etc/logcheck/logcheck.conf Main configuration.
/etc/logcheck/logcheck.logfiles.d/ Log sources to read.
/etc/logcheck/ignore.d.<level>/ Rules that drop lines from System Events.
/etc/logcheck/violations.d/ and violations.ignore.d/ Security Events matches and their filters.
/etc/logcheck/cracking.d/ Security Alerts matches.
/var/lib/logcheck/ Offsets (state). Delete a file here to reprocess that log.
/etc/cron.d/logcheck Schedule.

That is the whole tool. Install it, expect a noisy first week, write a few tight ignore rules each morning, and you end up with an inbox that only speaks when something on the box has changed.

Recent posts

  • If you've spent any time configuring user authentication on... Full Story

  • DNS is one of those technologies that quietly underpins... Full Story

  • BGP issues on FortiGate firewalls usually trace back to... Full Story

  • Every time your laptop talks to your router, a... Full Story

  • If you've spent any time configuring NAT on a... Full Story

  • If you have spent any time configuring firewall policies... Full Story

  • High availability on FortiGate is one of those features... Full Story

  • If you've configured SD-WAN on a FortiGate, you've almost... Full Story

  • FortiLink is the management protocol that turns a FortiSwitch... Full Story

  • FortiSwitches are pretty rock solid from Mean Time Between... Full Story

  • This is a quicky tip.  Have you ever gone... Full Story

  • DNS is one of those quiet pieces of internet... Full Story

  • This article is an updated version of the previous... Full Story

  • You will add ns2 as a secondary (slave) BIND9... Full Story

  • In the process of deploying my lab, I needed... Full Story

  • RFC 8805, used to be known as Self-Correcting IP... Full Story

  • Years back, I wrote an article about certificate pinning. ... Full Story

  • FortiGates have the ability to send alerts to Microsoft... Full Story

  • In this post, I am going to walk through... Full Story

  • Troubleshooting VoIP on a FortiGate can feel like trying... Full Story

  • Prior to FortiOS 7.0, there were three commands to... Full Story

  • In this post, I am going to go over... Full Story

  • What we are going to do:  We are going... Full Story

  • Choosing between FGCP (FortiGate Clustering Protocol) and FGSP (FortiGate... Full Story

  • Creating a VLAN on macOS (The "Pro" Move) A... Full Story

  • This blog post explores the logic behind how macOS... Full Story

  • Pretty Fly for a Wi-Fi Tell My Wi-Fi Love... Full Story

  • Part of my daily gig is creating BoMs (Bill-of-Materials)... Full Story

  • ICMP introduces several security risks, but careful filtering, rate... Full Story

  • The command diag debug application dhcps -1 enables full... Full Story

  • In the world of FortiOS, execute tac report is... Full Story

  • LLDP; What is it The Link Layer Discovery Protocol... Full Story

  • What it actually does When you run diagnose fdsm... Full Story

  • Monkey Bites are bite-sized, high-impact security insights designed for... Full Story

  • I have run macOS in macOS with Parallels but... Full Story

  • Don't be confused with my other FortiNAC posts where... Full Story

  • This is the third session in a multi-part article... Full Story

  • Today I was configuring key-based authentication on a FortiGate... Full Story

  • Netcat, often called the "Swiss Army knife" of networking,... Full Story

  • At its core, IEEE 802.1X is a network layer... Full Story

  • In case you did not see the previous FortiNAC... Full Story

  • This is our 5th session where we are going... Full Story

  • Now that we have Wireshark installed and somewhat configured,... Full Story

  • The Philosophy of Packet Analysis Troubleshooting isn't about looking... Full Story

  • For those that may not know, Fortinet has a... Full Story

  • Executive Summary Objective: Deploy logcheck on a Debian or... Full Story

  • Ettercap in 2026: ARP Poisoning, DNS Spoofing, and Content... Full Story