Scope
A technical self-assessment for entities in scope of the NIS2 Directive (Directive (EU) 2022/2555). Each item is a thing a sysadmin can verify on a host now — a command output, a config flag, a file’s contents, an external scan result — not a policy approval or a named role.
This is the box-level companion to
nis2-infrastructure. That guide
explains why each Article 21(2) measure matters and how to implement
it; this checklist is the “is it actually configured?” layer.
NIS2 also requires governance, supply-chain, and reporting work that does not appear on the box — those obligations are not omitted, but they are kept to a short closing section (9) rather than padded into technical-looking checkboxes. Work top-to-bottom.
Compliance references map only where they actually apply. They are not legal advice; for formal classification and audit defence, use qualified counsel and your competent authority’s published guidance.
1. Hardening baseline (Article 21(2)(a), (e), (g))
The documented baseline applied to every host. Verify on a sample host or, better, in configuration management.
- SSH password authentication off.
sshd -T | grep -i passwordauthenticationreturnspasswordauthentication no. Seessh-hardening. NIS2: 21(2)(e),(j); ISO 27001: A.8.5. - Root SSH login off.
sshd -T | grep -i permitrootloginreturnspermitrootlogin no. ISO 27001: A.8.2. - SSH key algorithms restricted to modern set.
sshd -T | grep -E '^(kexalgorithms|ciphers|macs)'lists only ed25519 /curve25519-sha256/aes*-gcm/hmac-sha2-*-etmvariants. NIS2: 21(2)(h). - Firewall default-deny.
ufw status verboseshowsDefault: deny (incoming)orfirewall-cmd --get-default-zonereturnsdrop/block. ISO 27001: A.8.20, A.8.22. - AppArmor / SELinux in enforcing mode.
aa-statusreports profiles in enforce mode, orgetenforcereturnsEnforcing. ISO 27001: A.8.7. - Per-human sudoer accounts only.
getent group sudo(Debian) orgetent group wheel(RHEL) lists named humans, not service accounts. NIS2: 21(2)(i); ISO 27001: A.5.16, A.8.5. - No unrestricted NOPASSWD sudo entries.
grep -r NOPASSWD /etc/sudoers /etc/sudoers.d/returns only specifically documented automation entries. ISO 27001: A.8.5. - Unused listening services removed.
ss -tlnpshows only services in the documented baseline;cups,bluetooth,avahi-daemon,postfix(if not sending) all absent. ISO 27001: A.8.9.
2. Patching and maintenance (Article 21(2)(e))
- Automatic security updates enabled. Debian-family:
apt-config dump APT::PeriodicshowsUpdate-Package-Lists "1",Unattended-Upgrade "1". RHEL-family:systemctl is-enabled dnf-automatic.timerreturnsenabled. NIS2: 21(2)(c); ISO 27001: A.8.8. - Reboot policy configured for kernel updates.
/etc/apt/apt.conf.d/50unattended-upgradesincludesUnattended-Upgrade::Automatic-Reboot "true"with aReboot-Time, or equivalent on RHEL. ISO 27001: A.8.8. - Patch evidence on the box.
tail -50 /var/log/unattended-upgrades/unattended-upgrades.logordnf historyshows recent automated runs. NIS2: 21(2)(f). -
lynisrun within the last 90 days.lynis show details LASTor the report file under/var/log/lynis*is dated within 90 days; hardening index recorded. NIS2: 21(2)(f); ISO 27001: A.5.35. -
oscapbaseline run within the last 90 days (RHEL family). Report file dated; failing rules tracked. NIS2: 21(2)(f). - Package sources pinned and authenticated.
apt-key list/dnf repolistshows only intended repos with valid GPG; no[trusted=yes]overrides. NIS2: 21(2)(d); ISO 27001: A.8.30.
3. Cryptography (Article 21(2)(h))
- Edge TLS protocols restricted.
nginx -T 2>/dev/null | grep ssl_protocolsreturnsTLSv1.2 TLSv1.3only. Seenginx-tls-2026. ISO 27001: A.8.24. - HSTS deployed with sane max-age.
curl -sI https://host | grep -i strict-transportreturnsmax-age≥31536000. ISO 27001: A.8.24. - OCSP stapling on.
openssl s_client -connect host:443 -status </dev/null 2>/dev/null | grep -i 'OCSP Response Status'returnssuccessful. ISO 27001: A.8.24. - External TLS scan grade A or A+ within the last 90 days.
Qualys SSL Labs or
testssl.shreport retained and dated. Seetls-audit. NIS2: 21(2)(f). - PostgreSQL TLS enabled for non-local connections.
psql -c 'SHOW ssl;'returnson;pg_hba.confuseshostsslfor every non-samehostentry. Seepostgresql-hardening. ISO 27001: A.8.24. - Redis plaintext port disabled.
redis-cli -p 6379 PINGfrom off-host fails;redis.confhasport 0andtls-port 6379(or equivalent). Seeredis-hardening. ISO 27001: A.8.24. - At-rest encryption on storage.
lsblk -o NAME,FSTYPEshowscrypto_LUKSon the data partition, or the cloud-provider console confirms volume encryption for the relevant disks. GDPR: Article 32; ISO 27001: A.8.24. - Backup repository encrypted.
restic snapshotsrequires a passphrase; passphrase is stored outside the host being backed up. Seeencrypted-backups-restic. GDPR: Article 32.
4. Access control and identity (Article 21(2)(i), (j))
- No shared interactive accounts.
awk -F: '$3>=1000 && $3<60000 {print $1}' /etc/passwdlists only named humans; nodeveloper,admin, or shared aliases. ISO 27001: A.5.16. -
authorized_keysaudit within the last 90 days. Every entry carries a dated# owner — added YYYY-MM-DDcomment; no orphaned keys from former staff. ISO 27001: A.5.18, A.8.5. - PostgreSQL roles least-privilege.
\dushows application roles withoutSuperuserorCreate role; replication on a dedicated replication role. ISO 27001: A.8.2. - Redis ACLs scoped.
ACL LISTshows thedefaultuser withoff nopass ~* &* -@all(or equivalent disabled) and per-purpose users with category limits. ISO 27001: A.8.2. - WordPress administrator accounts audited.
wp user list --role=administrator --format=tablereturns only expected named accounts. ISO 27001: A.5.18. - Cloud provider IAM: no long-lived root keys in use.
Provider console shows last-used dates on root credentials are
Never(AWS) or equivalent on other providers. ISO 27001: A.5.16, A.8.5. - Asset inventory file present and current. A versioned file or system of record listing every host, its purpose, the data it processes, and the owner — last reviewed within 90 days. ISO 27001: A.5.9.
5. Logging and detection (Article 21(2)(b))
-
auditdenabled with a baseline ruleset.systemctl is-active auditdreturnsactive;auditctl -llists rules — not empty. ISO 27001: A.8.15, A.8.16. - Logs forwarded off-host.
rsyslog/journal-upload/agent config present and reaching a remote target; remote ingest confirmed within last 24h. ISO 27001: A.8.15. - PostgreSQL audit-relevant logging on.
SHOW log_connections;andSHOW log_disconnections;both returnon;log_statementset per policy (ddlminimum). ISO 27001: A.8.15, A.8.16. - Nginx access logs retained per the documented policy.
Logrotate config matches the policy; oldest log file aligns
with retention. See
log-minimisation-recipes. GDPR: Article 5(1)(c), 5(1)(e). - Failed-auth detection wired up.
fail2ban-client statuslists active jails for at leastsshdand any other public-facing auth endpoint; or equivalent SIEM rules verified. ISO 27001: A.8.16.
6. Backups and recovery (Article 21(2)(c))
- Encrypted backup job scheduled.
systemctl list-timers --all | grep -i backup(or the cron equivalent) shows the schedule active and recently-run. ISO 27001: A.8.13. -
restic checkpasses within the last 30 days. Output retained; failures alert on. ISO 27001: A.8.13. - Last successful restore test within the last 6 months. Restored-target evidence held (a database row count, a file hash, a screenshot of the recovered service responding). ISO 27001: A.5.30.
- PostgreSQL WAL archiving on.
SHOW archive_mode;returnson;SHOW archive_command;is non-empty and not'true'or/bin/true. Seepostgres-backups. ISO 27001: A.8.13. - Backup retention enforced.
restic forget --dry-run(or equivalent) returns the expected pruning plan against the documented retention policy. GDPR: Article 5(1)(e).
7. MFA on remote interfaces (Article 21(2)(j))
These checks happen in the relevant control panel or via API, not on the host — but they are verifiable, point-in-time checks.
- Cloud provider portal: MFA enforced for every human user.
Provider console shows zero users with
MFA: not enabled. ISO 27001: A.8.5. - Code repository: org-level 2FA enforcement on. GitHub /
GitLab org settings show
Require two-factor authentication— enforcement, not just opt-in. ISO 27001: A.8.5. - CI/CD: short-lived tokens only. No long-lived personal access tokens in pipelines; OIDC or equivalent in use. ISO 27001: A.8.5.
- WordPress: 2FA plugin active for administrator role.
wp plugin list --status=active | grep -i -E 'two-factor|2fa'returns the configured plugin. ISO 27001: A.8.5. - Database admin tools (pgAdmin, RedisInsight, etc.) behind MFA or VPN. No public admin UIs reachable without an authenticated tunnel. ISO 27001: A.8.5, A.8.20.
8. External verification (Article 21(2)(f))
- TLS scan dated within last 90 days. Qualys SSL Labs or
testssl.shoutput retained; grade A or A+. NIS2: 21(2)(f). -
ssh-auditclean.ssh-audit hostreturns noFAILorLEGACYfindings on any public SSH endpoint. NIS2: 21(2)(f). - Public-facing vulnerability scan within last 90 days. Nessus, OpenVAS, or equivalent; report retained; findings tracked to closure or to an accepted-risk register. ISO 27001: A.5.35.
- External pen test within the cadence the entity has committed to (typically annual for in-scope services). Report and remediation log retained. ISO 27001: A.8.29.
9. Governance, supply-chain, and reporting
The checks above cover the technical surface of Article 21(2). NIS2
also requires governance and reporting work that does not appear on
a host — the minimum set is below, kept short. The reasoning for each
is in nis2-infrastructure.
- Information security policy approved by the management body, dated, with a defined review cadence. NIS2: 20(1), 21(2)(a).
- Risk register exists, lists infrastructure-level risks, is reviewed at least annually. NIS2: 21(2)(a), (f).
- Processor / supplier register exists with DPA references and security commitments per supplier. NIS2: 21(2)(d); GDPR: Article 28.
- Incident-response playbook covers the Article 23 timeline: 24-hour early warning, 72-hour notification, one-month final report — starting from awareness, not containment. NIS2: 23.
- Competent authority contact and reporting portal on file where the on-call can find them. NIS2: 23(1).
- Out-of-band incident communications channel exists and has been used in a drill. NIS2: 21(2)(j).
This checklist is the technical “is it configured?” companion to
nis2-infrastructure. When an item is
unclear, the reasoning is in that guide. For formal classification and
audit defence, work with qualified counsel and your competent
authority’s published guidance.