Debian GNU/Linux · Services

Confine services with systemd sandboxing options

When it fails: Network-facing services run with the full privileges systemd gives by default. A compromised service can read and change the whole system instead of its own files.

CB-DEB-SVC-025mediumactivepartialprofile server-hardened

As released in v0.1.0 beta · pre-release. Current state.

Description

systemd can confine each service with options in its unit or in a drop-in (systemctl edit <unit>): a dedicated or dynamic user (User=, DynamicUser=), a read-only view of the system (ProtectSystem=strict, ProtectHome=, ReadWritePaths=), a private /tmp and device set (PrivateTmp=, PrivateDevices=), no privilege gain (NoNewPrivileges=, CapabilityBoundingSet=), and kernel and system call filters (ProtectKernelTunables=, RestrictAddressFamilies=, SystemCallFilter=...).

systemd-analyze security scores each service from 0 (confined) to 10 (unconfined) and labels it OK, MEDIUM, EXPOSED or UNSAFE.

The check lists the services that systemd-analyze security labels UNSAFE with their score; it always passes, so the control ends as review. A person decides which network-facing services to confine first. Many Debian services already ship hardened units (for example systemd-resolved, chrony); OpenSSH stays largely unconfined by design, since it must start login sessions.

Rationale

Most daemons only need a few directories, capabilities and system calls. Confining them limits what an attacker gains by exploiting one: no access to other services' data, no kernel tuning, no new privileges. This is the compartmentalization ANSSI asks for each service.

Impact

Options that are too strict make a service fail at start-up or at run time (cannot write its files, cannot open a socket). Each change must be tested on the service and kept in a drop-in so package upgrades do not overwrite it.

Audit

  1. Run systemd-analyze security and note the services rated UNSAFE or EXPOSED.
  2. For each service that listens on the network or parses untrusted data, check that a drop-in under /etc/systemd/system/<unit>.d/ sets the sandboxing options it supports, and that systemd-analyze security <unit> shows an improved score.

Automated: every check must pass. Scanners report each check by its id.

exposure

Lists the services rated UNSAFE by systemd-analyze security, for review.

script: |
  command -v systemd-analyze >/dev/null 2>&1 || { echo "systemd-analyze not found"; exit 3; }
  o=$(systemd-analyze security --no-pager 2>/dev/null) || { echo "systemd-analyze security failed"; exit 3; }
  total=$(printf '%s\n' "$o" | awk 'NR > 1' | grep -c .)
  unsafe=$(printf '%s\n' "$o" | awk 'NR > 1 && $3 == "UNSAFE" { printf "%s=%s ", $1, $2 }')
  n=$(printf '%s' "$unsafe" | wc -w)
  echo "$n of $total services UNSAFE: $unsafe"

Remediation

For each service to confine, run systemctl edit <unit> and add the options it tolerates, for example:

[Service]
ProtectSystem=strict
ReadWritePaths=/var/lib/<service>
ProtectHome=yes
PrivateTmp=yes
PrivateDevices=yes
NoNewPrivileges=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6

Restart the service, check that it works and its logs (journalctl -u <unit>), then compare systemd-analyze security <unit>.

Rollback

Run systemctl revert <unit> to remove the drop-ins, then restart the service.

References

Mappings

FrameworkIDRelationNote
ANSSI-BP-028 - Recommandations de configuration d'un système GNU/Linux2.0R64partialCovers service privileges through systemd users and capabilities.
ANSSI-BP-028 - Recommandations de configuration d'un système GNU/Linux2.0R65partialCovers compartmentalization with systemd namespaces; containers and VMs are out of scope.
ANSSI-BP-028 - Recommandations de configuration d'un système GNU/Linux2.0R66partialCovers system call and kernel access filters set by systemd.
NIST SP 800-53 Rev. 55.1.1SC-39related
NIST SP 800-53 Rev. 55.1.1AC-6related

How this control relates to the other framework's: equivalent, stricter, looser, partial or related.

Threats mitigated

People and lifecycle

Authors
Verified2026-10-18 by Sn0wAlice on 12, Proxmox VM, Debian 12 genericcloud image, kernel 6.1.0-54-cloud-amd64. Check lists the UNSAFE services from systemd-analyze security and ends as review, on fresh and loaded systems.
Verified2026-10-18 by Sn0wAlice on 13, Proxmox VM, Debian 13 genericcloud image, kernel 6.12.113+deb13-cloud-amd64. Check lists the UNSAFE services from systemd-analyze security and ends as review, on fresh and loaded systems.
Introduced inv0.1.0
Created, updated2026-10-18, 2026-10-18
Translationsfr