The Complete Production SOP: How to Deploy and Run systemd Service Unit Hardening & Sandboxing Directives in Autonomous AI Agents
Production SOP to harden Linux systemd services in Codex, Claude Code, and Cursor. Audit security scores, configure ProtectSystem, and sandbox daemons.
Technical Overview & Architectural Context
Autonomous coding agents frequently generate naive systemd service units that run by default as root without filesystem isolation, memory isolation, or capability dropping. In typical devops generation prompts, agents emit generic [Service] blocks containing only `ExecStart` and `Restart=always`, leaving daemons fully exposed to host compromise, privilege escalation, and lateral movement if an unauthenticated remote code execution (RCE) payload targets the service. The systemd-service-unit-hardening skill enforces strict, deterministic sandboxing patterns across all generated or refactored unit files. By mandating directives like ProtectSystem=strict, ProtectHome=true, NoNewPrivileges=true, PrivateTmp=true, and explicit CapabilityBoundingSet restrictions, agents are constrained to build least-privilege service declarations that consistently score below 2.0 (OK / green band) on the systemd-analyze security auditing scale.
Prerequisites & Environment Requirements
Verified Search Intents & Long-Tail Queries Solved
This operational tutorial is engineered to provide deterministic solutions for these developer search queries:
Step-by-Step Execution Playbook
Local Environment Setup & SKILL.md Mounting
Mount the systemd hardening skill manifest into the agent's active execution context.
Autonomous agents discover behavioral rules through directory-level manifest injection. Mount the skill into `.cursor/skills/` or `~/.claude/skills/` so the agent actively checks its hardening SOP whenever systemd files (*.service) are inspected or generated.
mkdir -p .claude/skills/systemd-service-unit-hardening && curl -fsSL https://askills.dev/api/skills/systemd-service-unit-hardening/raw -o .claude/skills/systemd-service-unit-hardening/SKILL.md---
name: "systemd-service-unit-hardening"
description: "Lock down Linux system services using built-in systemd security sandboxing directives."
metadata:
author: "systemd"
version: "1.0.0"
runtime_compatibility:
- "codex"
- "claude-code"
- "cursor"
- "windsurf"
triggers:
- "harden systemd service"
- "systemd-analyze security"
- "protectsystem strict systemd"
permissions:
fs_read: true
fs_write: "workspace"
shell_exec: false
net_access: false
---Use `ProtectSystem=strict` paired with explicit `ReadWritePaths=` rather than relying on `ProtectSystem=full` to prevent write access anywhere outside declared data volumes.
Setting `ProtectHome=true` will completely hide `/home`, `/root`, and `/run/user`. If your application reads user-owned config files directly from `/home/user`, the daemon will fail with ENOENT.
Service Manifest Hardening Directives Injection
Apply fundamental process isolation, namespace encapsulation, and filesystem protection parameters.
Inject the core systemd sandboxing triad: namespaces (PrivateTmp, PrivateDevices, ProtectKernelTunables), process controls (NoNewPrivileges, RestrictSUIDSGID), and credential segregation (User, Group, DynamicUser).
systemd-analyze verify /etc/systemd/system/app.service[Unit]
Description=Production Node/Go API Service
After=network.target network-online.target
Wants=network-online.target
[Service]
Type=exec
User=appdaemon
Group=appdaemon
DynamicUser=true
ExecStart=/opt/api/bin/worker --config /etc/api/config.json
Restart=on-failure
RestartSec=5s
# Sandboxing & Filesystem Isolation
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
PrivateDevices=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
ProtectClock=true
# State & Logging Storage Permissions
StateDirectory=api-worker
LogsDirectory=api-worker
ConfigurationDirectory=api
# Privilege Management
NoNewPrivileges=true
CapabilityBoundingSet=
AmbientCapabilities=
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
RestrictNamespaces=true
RestrictRealtime=true
RestrictSUIDSGID=true
LockPersonality=true
MemoryDenyWriteExecute=true
[Install]
WantedBy=multi-user.targetWhen using `DynamicUser=true`, leverage `StateDirectory=foo` which automatically creates `/var/lib/foo` with safe permissions owned by the dynamic UID.
Setting `MemoryDenyWriteExecute=true` can break runtimes using Just-In-Time (JIT) compilers like V8 (Node.js) or JVM unless W^X is strictly supported.
Deterministic Triggering & Security Audit Inspection
Invoke the AI agent with specific hardening triggers and audit the service configuration score.
Instruct the autonomous agent to run `systemd-analyze security` against the generated service. The skill sets a firm threshold: the audit score must be strictly less than 2.0 (SAFE).
systemd-analyze security api-worker.serviceTarget an overall exposure score between 1.0 and 1.9; values below 2.0 are highlighted green by systemd's built-in auditing matrix.
Older Linux distributions running systemd < 239 may not recognize `ProtectControlGroups=` or `RestrictAddressFamilies=`, causing verification warnings or startup failures.
Verification, Linting & Output Quality Gate
Execute automated self-healing checks and unit verification before promoting the configuration.
Require the agent to validate syntax via `systemd-analyze verify`, reload the daemon, and perform an isolated startup check to verify that no required device nodes or system calls were inadvertently masked.
systemd-analyze verify ./api-worker.service && sudo systemctl daemon-reload && sudo systemctl restart api-worker.serviceInspect transient systemd journal logs using `journalctl -u api-worker -b --no-pager -n 50` immediately after hardening to detect silent EPERM failures.
Failure to run `systemctl daemon-reload` leaves modified directives inactive on disk while the in-memory manager runs old unhardened profiles.
Real-World Scenario: Harden Legacy Unconfined Python Backend Service Unit
“Refactor our unhardened payment webhook unit file at /etc/systemd/system/webhook.service. It currently runs as root and writes logs to /var/log/webhook.log. Apply systemd-service-unit-hardening rules, isolate the filesystem, eliminate root execution, and ensure systemd-analyze security score is under 2.0.”
Runtime Troubleshooting & Failure Modes
Root Cause: systemd failed to create a mount namespace for the process, typically triggered when ProtectSystem=strict, PrivateTmp=true, or ReadWritePaths= attempts to bind mount a path that does not exist or traverses an unreadable mount point.
Ensure all specified paths exist before daemon startup, or prefix optional paths with a minus sign (e.g., `ReadWritePaths=-/var/log/optional-dir`). Verify that mount propagation is not conflicting.Root Cause: The service is running inside an unprivileged Docker container or LXC guest lacking CAP_SYS_ADMIN, preventing systemd from spawning new mount namespaces required for PrivateTmp and ProtectSystem.
Run the verification inside a genuine virtual machine or configure the container runtime with `--cap-add=CAP_SYS_ADMIN` and mount `/sys/fs/cgroup` appropriately for nested systemd operation.Frequently Asked Questions (systemd Service Unit Hardening & Sandboxing Directives SOP)
Q:Can I use systemd Service Unit Hardening & Sandboxing Directives across Codex, Claude Code, and Cursor simultaneously?
Yes. The skill conforms to the universal SKILL.md specification. When placed in the project root (.agents/skills/ or .claude/skills/), any modern agent runtime (Codex, Claude Code CLI, Cursor, Windsurf) will automatically detect the frontmatter triggers and enforce unit hardening rules.
Q:How does systemd Service Unit Hardening & Sandboxing Directives prevent context window overflow during long agent sessions?
Instead of loading entire Linux man pages into prompt contexts, this skill provides a concise procedural checklist (ProtectSystem, DynamicUser, CapabilityBoundingSet, syscall filtering) and verification steps, minimizing token consumption while guaranteeing deterministic, high-scoring configuration files.
Q:Does this skill require escalated root or container permissions?
Writing and refining the `.service` unit files does not require root permissions inside your IDE workspace (Security Score 98/100). Escalate to sudo privileges only when moving the validated files to `/etc/systemd/system/` and invoking `systemctl daemon-reload`.
Ready to equip your autonomous agent with systemd Service Unit Hardening & Sandboxing Directives?
Copy the complete audited SKILL.md specification or download the 1-click zip bundle directly from our verified registry.