NIS2, ISO 27001 & evidencebeginner8 min read

NIS2 checklist for the Belgian SME: the ten measures of Article 21 translated into concrete server tasks

NIS2 Article 21(2) lists ten measures in legal language. This is the translation into what you do on your servers on Monday — per measure the command, the file or the script that produces the evidence. With the Belgian context: the law of 26 April 2024, the CCB, CyberFundamentals and the registration duty.

Contents
  1. First: the Belgian context in five points
  2. The ten measures, translated
  3. The checklist (to tick off)
  4. Pitfalls
  5. What you still don't have
  6. How monsys does it
  7. FAQ

The NIS2 directive was transposed in Belgium by the law of 26 April 2024, in force since 18 October 2024. The Centre for Cybersecurity Belgium (CCB) is the competent authority, and organisations in scope had to register on Safeonweb@Work. Since then the question in every IT department of an "important" or "essential" entity has been the same: what do I actually have to do now?

This article answers that for the server estate. It is not legal advice and not a compliance statement — whether your entity falls under the law, in which category, and whether your measures are "appropriate and proportionate" (the words of the law) is for a lawyer or a CyFun-accredited auditor to judge. What's here is how to get the technical evidence ready so that judgement goes quickly.

First: the Belgian context in five points

  1. Two categories. Essential entities (large companies in sectors such as energy, transport, health, digital infrastructure) and important entities (medium-sized ones in the same sectors, plus sectors like postal services, waste, chemicals, food, manufacturing, digital services). The thresholds are 50 employees or €10 million turnover — so many SMEs fall below, but not all.
  2. CyberFundamentals (CyFun). The CCB has its own framework with three levels: Basic, Important, Essential. Important entities can demonstrate conformity via CyFun Important; essential ones via CyFun Essential or ISO 27001. A CyFun certificate from an accredited body counts as a presumption of conformity.
  3. Notification duty. A significant incident: early warning within 24 hours, incident notification within 72 hours, final report within a month. Via the CCB notification platform.
  4. Board liability. The board must approve the measures, oversee their implementation, and follow training. That's new and it's personal.
  5. Supervision. The CCB can inspect, request audits and impose fines (up to €10 million or 2% of turnover for essential; €7 million or 1.4% for important).

The ten measures, translated

Article 21(2) of the directive (adopted in the Belgian law) names ten domains, (a) to (j). Per domain: what the law says, what that means on a server, and the command or file that is the evidence.

(a) Risk analysis and security policy

Law: policies on risk analysis and information system security. Server: you can't analyse the risk of what you don't know. Start with an inventory you can reproduce.

# Per host, weekly, into git or a shared directory:
{
  echo "host=$(hostname -f) date=$(date -Is)"
  echo "os=$(. /etc/os-release; echo "$PRETTY_NAME") kernel=$(uname -r)"
  echo "ip=$(hostname -I)"
  echo "--- listening"; ss -tulnH | awk '{print $1, $5}' | sort -u
  echo "--- services"; systemctl list-units --type=service --state=running --no-legend | awk '{print $1}'
  echo "--- packages"; dpkg-query -W -f='${Package} ${Version}\n' | wc -l
  echo "--- users"; awk -F: '$3>=1000 && $7!~/nologin|false/{print $1}' /etc/passwd
} > "/srv/inventory/$(hostname -s)-$(date +%F).txt"

The risk analysis itself is a document (which systems, which threats, which impact, which measure). You don't write that in bash. But every line in that document refers to an asset from this inventory — that's the link an auditor looks for.

(b) Incident handling

Law: incident handling procedures. Server: you must be able to see incidents (detection), reconstruct them (logs kept long enough) and report them (within 24 h).

# Keep logs long enough (journald): at least 90 days, preferably 12 months for auth
sudo mkdir -p /etc/systemd/journald.conf.d
sudo tee /etc/systemd/journald.conf.d/retention.conf >/dev/null <<'EOF'
[Journal]
Storage=persistent
SystemMaxUse=2G
MaxRetentionSec=365day
EOF
sudo systemctl restart systemd-journald

# Time must be right, otherwise every timeline is worthless
timedatectl show -p NTPSynchronized -p Timezone

Detection: see the guides on SSH brute force and honeypot files. The procedure (who calls whom, who notifies the CCB, where the form is) is a single sheet on the wall — that you rehearse once a year.

(c) Business continuity: backup, recovery, crisis management

Law: business continuity, such as backup management and disaster recovery plans. Server: a backup you've never restored is a hypothesis.

# Evidence 1: backup is recent
restic -r /srv/backup snapshots --latest 1 --json | jq -r '.[0].time'
# Evidence 2: backup is readable (sample 5% of the data)
restic -r /srv/backup check --read-data-subset=5%
# Evidence 3: restore test, with date and result logged
restic -r /srv/backup restore latest --target /tmp/restore-test --include /etc/nginx \
  && echo "$(date -Is) restore-test OK nginx-config" >> /srv/inventory/restore-tests.log

Quarterly rhythm: one full restore test of a real service to a test environment. See verifying backups that say "succeeded".

(d) Supply chain security

Law: supply chain security, including the relationship with direct suppliers. Server: know which third-party software you run and which vulnerabilities it brings — OS packages and application dependencies.

# OS layer: see the OSV guide; in short
dpkg-query -W -f='${source:Package} ${source:Version}\n' | sort -u > /srv/inventory/$(hostname -s)-packages.txt
# Application layer: lockfiles are your SBOM-light
find /srv /var/www /opt -maxdepth 4 \( -name package-lock.json -o -name requirements.txt -o -name composer.lock -o -name go.sum \) 2>/dev/null

The contractual side (which requirements you impose on suppliers, whether they have a NIS2 or ISO statement themselves) is a list in your supplier register. The technical side is a CVE scan with a date.

(e) Acquisition, development and maintenance; vulnerability handling

Law: security in acquisition, development and maintenance, including vulnerability handling and disclosure. Server: patching, with a demonstrable lead time.

# Automatic security updates on
sudo apt install -y unattended-upgrades
grep -E '^Unattended-Upgrade::Allowed-Origins|security' /etc/apt/apt.conf.d/50unattended-upgrades | head -3
# Evidence: when was what installed
grep -h 'status installed' /var/log/dpkg.log* | awk '{print $1, $5, $6}' | sort | tail -20
# Pending updates and reboot status
apt list --upgradable 2>/dev/null | wc -l; [ -f /var/run/reboot-required ] && echo REBOOT-REQUIRED

See configuring unattended-upgrades properly. An auditor asks about the time between publication of a fix and installation. dpkg.log gives the installation date; the USN gives the publication date.

(f) Assessing effectiveness

Law: policies and procedures to assess the effectiveness of the measures. Server: measure. A measure without a metric is an intention.

MeasureMetricSource
Patchingdays between USN and installation, p50 and p95dpkg.log + USN date
Backup% of days with a successful backup; last restore testrestic snapshots + restore log
Detectionnumber of detections per month; % reviewed within 1 hntfy log / ticket system
Accessnumber of accounts; % with MFA; date of last review/etc/passwd, IdP, review log

One page, updated every quarter, signed by the person responsible. That is "assessing effectiveness".

(g) Cyber hygiene and training

Law: basic cyber hygiene practices and training. Server: the basics aren't exciting, which is exactly why they get skipped.

# No password SSH, no root login
sshd -T | grep -E '^(passwordauthentication|permitrootlogin) '
# Firewall on, default deny
sudo ufw status verbose | head -4
# No accounts without a password
sudo awk -F: '($2=="" || $2=="!") {print "no-password:", $1}' /etc/shadow
# Session timeout on servers: TMOUT in /etc/profile.d
grep -rh TMOUT /etc/profile.d/ 2>/dev/null

Training: the law requires the board to be trained too. Keep the attendance list.

(h) Cryptography and encryption

Law: policies on the use of cryptography and, where appropriate, encryption. Server: TLS everywhere, no expired certificates, encrypted backups and disks.

# Which certificates are running, and when do they expire? (every listening TLS port)
for port in $(ss -tlnH | awk '{sub(/.*:/,"",$4); print $4}' | sort -un); do
  end=$(echo | timeout 3 openssl s_client -connect "localhost:$port" -servername "$(hostname)" 2>/dev/null \
        | openssl x509 -noout -enddate 2>/dev/null) && echo "port $port: $end"
done
# TLS configuration: no TLS 1.0/1.1
nmap --script ssl-enum-ciphers -p 443 localhost 2>/dev/null | grep -E 'TLSv1\.[01]' && echo "OLD PROTOCOL ACTIVE"
# Backup encrypted? (restic: always; rsync: no)
restic -r /srv/backup cat config >/dev/null 2>&1 && echo "restic repo: encrypted"
# Disk encryption
lsblk -o NAME,TYPE,FSTYPE | grep -i crypt

See TLS certificates that expire silently for the fleet-wide version.

(i) Human resources security, access control and asset management

Law: human resources security, access control policies and asset management. Server: who has access, why, and since when — and is that reviewed every quarter?

# All interactive accounts, with last SSH login from the journal
# (lastlog/wtmp are no longer reliable on Ubuntu ≥ 24.04; the journal is)
for u in $(awk -F: '$3>=1000 && $7!~/nologin|false/{print $1}' /etc/passwd); do
  last=$(journalctl -u ssh --since "365 days ago" --no-pager -o short-iso 2>/dev/null \
         | grep -E "Accepted (publickey|password) for $u " | tail -1 | awk '{print $1}')
  printf '%-16s last=%s\n' "$u" "${last:-never}"
done
# Who may sudo?
getent group sudo admin wheel 2>/dev/null
grep -rhE '^[^#].*ALL' /etc/sudoers /etc/sudoers.d/ 2>/dev/null
# Which SSH keys are authorised, and whose?
for d in /root /home/*; do [ -f "$d/.ssh/authorized_keys" ] && { echo "== $d"; awk '{print $NF}' "$d/.ssh/authorized_keys"; }; done

Every quarter: lay this output next to the staff list, explain or remove every discrepancy, and keep the result with date and signature. That's an access review, and it's the piece of evidence most often missing.

(j) Multi-factor authentication and secured communications

Law: use of MFA or continuous authentication, secured voice, video and text communications, and secured emergency communications. Server: SSH with keys is one factor (something you have). For admin access you want two.

# Option 1: key + TOTP via PAM (google-authenticator-libpam, no Google service needed)
sudo apt install -y libpam-google-authenticator
# per admin: google-authenticator -t -d -f -r 3 -R 30 -W
# in /etc/pam.d/sshd:  auth required pam_google_authenticator.so
# in sshd_config.d:    KbdInteractiveAuthentication yes
#                      AuthenticationMethods publickey,keyboard-interactive
# Option 2: SSH certificates with short TTL from a CA behind your IdP (MFA happens at the IdP)
# Evidence: which method is enforced?
sshd -T | grep -iE '^authenticationmethods'

Secured emergency communications: if your email and Teams are down because of the incident, how do you reach each other? A Signal group with the numbers on paper is a valid answer. Write it down.

The checklist (to tick off)

#MeasureServer evidence ready?Frequency
aInventory per host, linked to risk analysis☐weekly, automated
bLog retention ≥ 90 d, NTP synced, detection active, notification procedure on one sheet☐continuous / annual exercise
cBackup recent + check + restore test logged☐daily / quarterly
dPackage inventory + CVE scan with date; supplier register☐weekly
eunattended-upgrades on; dpkg.log kept; reboot-required watched☐continuous
fMetrics page with four KPIs, signed☐quarterly
gKey-only SSH, firewall default-deny, no empty passwords; training list☐continuous / annual
hCert inventory + expiry alert; TLS ≥ 1.2; encrypted backups☐continuous
iAccess review: accounts, sudo, SSH keys against staff list☐quarterly
jMFA enforced on admin access; emergency communications described☐continuous

Pitfalls

  • Thinking CyFun Basic is enough. Basic is for micro-organisations and non-NIS2 entities. Important entities sit at Important, and that level explicitly requires logging, vulnerability management and MFA.
  • Policy without evidence. A beautiful information security policy in Word is step one. The auditor asks: "show me that it runs". Every command in this article is that "showing".
  • Evidence without a date. A screenshot of apt list --upgradable without a timestamp proves nothing. Everything you keep gets a date -Is and goes into a directory you never modify again.
  • Forgetting to rehearse the 24-hour notification. Who calls the CCB when the IT lead is on holiday? If the answer is "erm", the procedure isn't finished.
  • Forgetting suppliers. Your cloud hoster, your MSP, your SaaS accounting: NIS2 requires you to assess their security. Ask for their statements and keep them.

What you still don't have

Every command above works on one server. With ten servers you have ten inventories, ten package lists, ten access-review outputs — and the question "is everything covered?" is a spreadsheet someone maintains. With thirty servers nobody maintains that spreadsheet. And the evidence you collect only becomes evidence when you can show it wasn't modified afterwards — a directory of text files isn't that.

How monsys does it

monsys maps every NIS2 measure (and the ISO 27001 and CRA controls) to an evidence query that runs continuously across all hosts: inventory, patch status, CVEs, backup freshness, certificates, accounts, MFA status, detections. The result is a coverage percentage per control and a monthly audit pack — Ed25519-signed, byte-stable, offline-verifiable — that you hand to a CyFun auditor or the CCB. A control that loses evidence (a host where unattended-upgrades stops working) raises a compliance erosion alert before the auditor sees it. monsys doesn't judge whether you're compliant; it makes sure the evidence is there when someone asks.

FAQ

Does my SME fall under NIS2?

That depends on sector and size (from 50 employees or €10 million turnover in a NIS2 sector, with downward exceptions for some sectors such as DNS and trust services). The CCB has a self-test on Safeonweb@Work. When in doubt: ask a lawyer; the registration duty is yours.

Is ISO 27001 the same as NIS2-compliant?

No, but it helps. For essential entities the CCB accepts an ISO 27001 certificate as a presumption of conformity, provided the scope fits. For important entities CyFun Important is the reference. The technical measures overlap largely; the notification duty and the board obligations come on top.

How fast do I have to report an incident?

Early warning within 24 hours of becoming aware of a significant incident, full notification within 72 hours, final report within a month. What's "significant" is defined in the law (severe operational disruption or financial loss, or considerable damage to others). When in doubt: report.

Written by the monsys team — sysadmins who do this every day.

Done it by hand? Let monsys keep it running.

Everything in this guide runs in monsys as a continuous check, with history, alerts and audit evidence. 5 servers free, EU-hosted in Belgium, installed in 60 seconds.