Skip to content

Field note

A Practical systemd Service Sandbox

Give the service a smaller operating space and prove it can still do its job.

Published17 Oct 2026

Updatedyesterday

Read time4 min. 819 words.

A small web application or background worker may run with far more access than its normal work requires. systemd provides service-level controls that can reduce that access, but a copied hardening block can also prevent uploads, certificate renewal or a scheduled maintenance task.

Choose one service and identify its real requirements before editing the unit. This approach suits a conventional system service on a supported Linux distribution. Feature availability and behaviour depend on the installed systemd version, kernel and execution environment; check the host's manual pages.

Map the writes and privileges

Record the service account, executable, configuration files, secrets, writable state, logs, temporary files and network dependencies. Include startup, upgrades, background jobs and shutdown. A service that starts successfully may still fail when it first tries to generate a report.

Separate immutable application code from writable data where the application supports it. That makes the permissions easier to understand. Establish why the service needs elevated privileges, if it currently runs as root, and whether its supported deployment can use a dedicated account instead.

Check access through local sockets and other services too. Filesystem restrictions alone do not describe everything the process can ask another privileged component to do.

Introduce a small set of compatible restrictions

The systemd execution manual describes controls such as NoNewPrivileges, PrivateTmp, ProtectSystem and ReadWritePaths. They address different boundaries: acquiring additional privilege, temporary-file visibility and filesystem writes.

For an application that supports these constraints, a proposed service drop-in might contain:

[Service]
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ReadWritePaths=/var/lib/example-service

This is a review example, not a universal baseline. The writable directory must already be suitable for the service and have appropriate ownership. A filesystem exception does not grant ordinary Unix permissions. PrivateTmp changes what the service sees in temporary directories, which can break intentional sharing with another process.

With ProtectSystem=strict, the writable exceptions need particular attention. Include only the paths the service requires, and check whether systemd's dedicated state or log directory settings are more appropriate. The manual also documents limitations: these controls rely on underlying kernel facilities and do not prevent all communication through local sockets.

Apply the first changes to a representative test instance using the distribution's supported drop-in mechanism. Preserve the previous configuration and keep the rollback limited to the added override. Avoid editing a vendor-supplied unit file that a package update may replace.

Add resource limits from measured use

Resource controls can stop a faulty worker from consuming the host, but arbitrary limits can create a new outage. Observe normal load, startup peaks, batch work and expected growth before choosing them.

For memory, systemd distinguishes a pressure control such as MemoryHigh from the harder MemoryMax boundary. Exceeding a hard limit can lead to a process being killed within the unit. The resource-control manual describes these behaviours and parent-slice effects.

Test how the application behaves near its chosen limits. Does it reject work clearly, retry indefinitely or lose an in-progress task? Include monitoring for throttling and memory-related termination, and decide who can adjust the limit when workload changes.

Use the exposure report as a review aid

This read-only command helps identify configured restrictions:

systemd-analyze security example-service.service

The systemd-analyze manual explains that its exposure assessment covers systemd's own service controls. It does not establish whether the application has a vulnerability or account for every protection implemented elsewhere.

Review the individual findings against the service's needs. A control that breaks essential functionality should prompt an architectural discussion or documented exception, not a blind change to improve a number. Conversely, a reassuring score is no reason to ignore an exposed admin interface or a credential readable by the application.

Verify normal work and prohibited work

Exercise the service's important functions on the test instance: startup, authentication, normal requests, file creation, background processing and restart. Check that expected data persists and that logs remain available.

Use a controlled test to confirm that the service identity cannot write to an agreed disposable location outside its permitted area. Check behaviour through the service's actual execution context, not an unrelated administrator shell. Inspect failures for missing permissions before broadening an exception.

Deploy during a suitable window, retain the previous configuration and watch the next scheduled workload. Record the reason for each exception. Revisit the restrictions when the application gains a new feature or changes its storage layout, so the operating boundary remains understandable.

References

Related notes

Need help mapping this to your own tenant, controls, or assessment timeline?