systemd-units
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSystemd Units
Systemd 服务单元
Overview
概述
This skill provides guidance for creating and hardening systemd service unit files following modern Linux service management best practices. It covers proper service type selection, dependency management, security sandboxing, and filesystem isolation to create reliable, secure services.
本技能提供遵循现代Linux服务管理最佳实践创建和加固systemd服务单元文件的指导。内容包括正确的服务类型选择、依赖管理、安全沙箱以及文件系统隔离,以创建可靠、安全的服务。
When to Use This Skill
适用场景
Use this skill when:
- Creating new systemd service units for web applications, APIs, background workers, or daemons
- Hardening existing service files with security and sandboxing options
- Converting traditional init scripts or manual process management to systemd
- Troubleshooting service startup, restart, or permission issues
- Implementing proper service dependencies and ordering
在以下场景中使用本技能:
- 为Web应用、API、后台工作进程或守护进程创建新的systemd服务单元
- 使用安全和沙箱选项加固现有服务文件
- 将传统init脚本或手动进程管理转换为systemd管理
- 排查服务启动、重启或权限问题
- 实现合理的服务依赖与启动顺序
Workflow Decision Tree
工作流决策树
User request involves systemd service?
│
├─ Creating a new service?
│ │
│ ├─ Web application/API → Use "Creating a New Service" workflow
│ │ → Start from assets/basic-webapp.service or assets/hardened-webapp.service
│ │
│ ├─ Background worker/daemon → Use "Creating a New Service" workflow
│ │ → Start from assets/background-worker.service
│ │
│ └─ One-time initialization → Use "Creating a New Service" workflow
│ → Start from assets/oneshot-init.service
│
└─ Hardening existing service?
│
└─ Use "Hardening an Existing Service" workflow
→ Reference references/systemd_options.md for security options
→ Compare against assets/hardened-webapp.service for patterns用户需求涉及systemd服务?
│
├─ 创建新服务?
│ │
│ ├─ Web应用/API → 使用「创建新服务」工作流
│ │ → 从assets/basic-webapp.service或assets/hardened-webapp.service开始
│ │
│ ├─ 后台工作进程/守护进程 → 使用「创建新服务」工作流
│ │ → 从assets/background-worker.service开始
│ │
│ └─ 一次性初始化任务 → 使用「创建新服务」工作流
│ → 从assets/oneshot-init.service开始
│
└─ 加固现有服务?
│
└─ 使用「加固现有服务」工作流
→ 参考references/systemd_options.md中的安全选项
→ 对照assets/hardened-webapp.service中的配置模式Creating a New Service
创建新服务
When creating a new systemd service, follow these steps:
创建新的systemd服务时,请遵循以下步骤:
1. Select the Appropriate Template
1. 选择合适的模板
Start with the most relevant template from :
assets/- : Simple web application without heavy sandboxing (development/internal use)
basic-webapp.service - : Production web application with full security hardening
hardened-webapp.service - : Queue processor, scheduled task, or background daemon
background-worker.service - : One-time initialization script or setup task
oneshot-init.service
Copy the template and customize the following sections in order:
从中选择最相关的模板开始:
assets/- :无重度沙箱的简单Web应用(开发/内部使用)
basic-webapp.service - :具备完整安全加固的生产环境Web应用
hardened-webapp.service - :队列处理器、定时任务或后台守护进程
background-worker.service - :一次性初始化脚本或设置任务
oneshot-init.service
复制模板并按顺序自定义以下部分:
2. Configure [Unit] Section
2. 配置[Unit]段
Update the service metadata and dependencies:
ini
[Unit]
Description=Clear description of what this service does
Documentation=https://example.com/docs or man:program(8)
After=network-online.target database.service
Wants=network-online.target
Requires=database.serviceKey decisions:
- After=: List services this must start after (ordering dependency)
- Wants=: Soft dependencies (service will start even if these fail)
- Requires=: Hard dependencies (service fails if these fail)
- For web services, always include and
After=network-online.targetWants=network-online.target
更新服务元数据和依赖关系:
ini
[Unit]
Description=清晰描述该服务的功能
Documentation=https://example.com/docs 或 man:program(8)
After=network-online.target database.service
Wants=network-online.target
Requires=database.service关键决策:
- After=:列出该服务必须在其之后启动的服务(启动顺序依赖)
- Wants=:软依赖(即使这些依赖启动失败,本服务仍会启动)
- Requires=:硬依赖(如果这些依赖启动失败,本服务也会启动失败)
- 对于Web服务,务必包含和
After=network-online.targetWants=network-online.target
3. Configure Service Type and Execution
3. 配置服务类型与执行参数
Select the appropriate service type based on the application's capabilities:
Recommended service types (in order of preference):
- : Application supports sd_notify protocol (best option for reliability)
Type=notify - : Standard long-running process (good default)
Type=exec - : One-time execution that exits (initialization scripts)
Type=oneshot
Avoid (poor error detection) and avoid (deprecated pattern).
Type=simpleType=forkingini
[Service]
Type=exec
ExecStart=/usr/bin/node /opt/webapp/server.js
WorkingDirectory=/opt/webappAlways use absolute paths for and related commands.
ExecStart=根据应用的能力选择合适的服务类型:
推荐的服务类型(按优先级排序):
- :应用支持sd_notify协议(可靠性最佳选项)
Type=notify - :标准长期运行进程(良好的默认选项)
Type=exec - :执行一次后退出的任务(初始化脚本)
Type=oneshot
避免使用(错误检测能力差)和****(已弃用模式)。
Type=simpleType=forkingini
[Service]
Type=exec
ExecStart=/usr/bin/node /opt/webapp/server.js
WorkingDirectory=/opt/webappExecStart=4. Configure User and Environment
4. 配置用户与环境变量
Set the execution user and environment variables:
ini
undefined设置执行用户和环境变量:
ini
undefinedOption 1: Dynamic user (recommended for security)
选项1:动态用户(安全性推荐)
DynamicUser=yes
DynamicUser=yes
Option 2: Specific user/group
选项2:指定用户/用户组
User=webapp
Group=webapp
User=webapp
Group=webapp
Environment configuration
环境变量配置
Environment="NODE_ENV=production"
EnvironmentFile=-/etc/webapp/webapp.env
**Best practice**: Use `DynamicUser=yes` for services that don't need a specific user. For secrets, use `EnvironmentFile=` with restricted permissions instead of embedding credentials in the service file.Environment="NODE_ENV=production"
EnvironmentFile=-/etc/webapp/webapp.env
**最佳实践**:如果服务不需要特定用户,请使用`DynamicUser=yes`。对于敏感信息,使用权限受限的`EnvironmentFile=`,而非将凭据嵌入服务文件中。5. Configure Restart Policy
5. 配置重启策略
Set appropriate restart behavior:
ini
Restart=on-failure # For web apps (restart on crashes)
RestartSec=10 # Wait 10 seconds before restart
TimeoutStartSec=30 # Fail if startup takes >30 seconds
TimeoutStopSec=30 # Force kill if graceful stop takes >30 secondsCommon patterns:
- Web applications: with
Restart=on-failureRestartSec=10 - Critical workers: with
Restart=alwaysRestartSec=5 - Oneshot tasks: Omit (default is no restart)
Restart=
设置合适的重启行为:
ini
Restart=on-failure # Web应用适用(崩溃时重启)
RestartSec=10 # 重启前等待10秒
TimeoutStartSec=30 # 启动耗时超过30秒则判定失败
TimeoutStopSec=30 # 优雅停止耗时超过30秒则强制终止常见模式:
- Web应用:搭配
Restart=on-failureRestartSec=10 - 关键工作进程:搭配
Restart=alwaysRestartSec=5 - 一次性任务:省略(默认不重启)
Restart=
6. Apply Security Hardening
6. 应用安全加固
For production services, apply progressive security hardening:
Start with these baseline options:
ini
undefined对于生产环境服务,逐步应用安全加固配置:
基础安全选项:
ini
undefinedFilesystem protection
文件系统保护
ProtectSystem=strict # Entire filesystem read-only except specified paths
ProtectHome=yes # Hide /home directories
PrivateTmp=yes # Private /tmp namespace
ReadWritePaths=/var/lib/myapp /var/log/myapp # Writable paths whitelist
NoNewPrivileges=yes # Prevent privilege escalation
ProtectSystem=strict # 整个文件系统只读,除指定路径外
ProtectHome=yes # 隐藏/home目录
PrivateTmp=yes # 私有/tmp命名空间
ReadWritePaths=/var/lib/myapp /var/log/myapp # 可写路径白名单
NoNewPrivileges=yes # 防止权限提升
Device and kernel protection
设备与内核保护
PrivateDevices=yes # Restrict device access
ProtectKernelTunables=yes # Prevent /proc/sys, /sys writes
ProtectKernelModules=yes # Prevent kernel module loading
ProtectControlGroups=yes # Protect cgroup filesystem
**For internet-facing services, add:**
```iniPrivateDevices=yes # 限制设备访问
ProtectKernelTunables=yes # 禁止写入/proc/sys、/sys
ProtectKernelModules=yes # 禁止加载内核模块
ProtectControlGroups=yes # 保护cgroup文件系统
**面向互联网的服务额外添加:**
```iniNetwork restrictions
网络限制
RestrictAddressFamilies=AF_INET AF_INET6 # Only IPv4/IPv6
RestrictAddressFamilies=AF_INET AF_INET6 # 仅允许IPv4/IPv6
Capability restrictions
权限限制
CapabilityBoundingSet= # Remove all capabilities
CapabilityBoundingSet= # 移除所有权限
System call filtering
系统调用过滤
SystemCallFilter=@system-service
SystemCallArchitectures=native
SystemCallFilter=@system-service
SystemCallArchitectures=native
Memory protection
内存保护
MemoryDenyWriteExecute=yes # W^X protection
LockPersonality=yes
**Testing strategy**: Start with maximum restrictions. If the service fails, use `journalctl -xeu <service>` to identify which restriction caused the failure, then selectively relax only that restriction.
Use `systemd-analyze security <service>` to verify the security posture after configuration.MemoryDenyWriteExecute=yes # W^X保护
LockPersonality=yes
**测试策略**:从最严格的限制开始。如果服务启动失败,使用`journalctl -xeu <service>`排查是哪项限制导致的问题,然后仅选择性放宽该项限制。
配置完成后,使用`systemd-analyze security <service>`验证安全状态。7. Configure [Install] Section
7. 配置[Install]段
Set the target for service enablement:
ini
[Install]
WantedBy=multi-user.target # Most common target (non-graphical multi-user system)Common targets:
- : Standard for most services
multi-user.target - : Services requiring graphical environment
graphical.target - : Alias for the default system target
default.target
设置服务启用的目标:
ini
[Install]
WantedBy=multi-user.target # 最常用的目标(非图形化多用户系统)常见目标:
- :大多数服务的标准目标
multi-user.target - :需要图形环境的服务
graphical.target - :默认系统目标的别名
default.target
8. Install and Test the Service
8. 安装并测试服务
Place the service file and test:
bash
undefined放置服务文件并进行测试:
bash
undefinedCopy to system directory
复制到系统目录
sudo cp myapp.service /etc/systemd/system/
sudo cp myapp.service /etc/systemd/system/
Reload systemd to recognize new service
重新加载systemd以识别新服务
sudo systemctl daemon-reload
sudo systemctl daemon-reload
Start and check status
启动并检查状态
sudo systemctl start myapp
sudo systemctl status myapp
sudo systemctl start myapp
sudo systemctl status myapp
View logs
查看日志
journalctl -xeu myapp
journalctl -xeu myapp
Enable to start on boot
设置开机自启
sudo systemctl enable myapp
undefinedsudo systemctl enable myapp
undefinedHardening an Existing Service
加固现有服务
When hardening an existing service file, follow these steps:
加固现有服务文件时,请遵循以下步骤:
1. Analyze Current Configuration
1. 分析当前配置
Read the existing service file and identify security gaps:
bash
undefined读取现有服务文件并识别安全漏洞:
bash
undefinedCheck current security exposure
检查当前安全风险
systemd-analyze security <service-name>
systemd-analyze security <service-name>
Review current configuration
查看当前配置
systemctl cat <service-name>
Look for:
- Missing sandboxing options (ProtectSystem, PrivateDevices, etc.)
- Overly permissive user (running as root unnecessarily)
- Missing filesystem restrictions
- No capability boundariessystemctl cat <service-name>
重点关注:
- 缺失的沙箱选项(ProtectSystem、PrivateDevices等)
- 权限过于宽松的用户(不必要地以root运行)
- 缺失的文件系统限制
- 未设置权限边界2. Create Drop-in Override
2. 创建Drop-in覆盖配置
Rather than modifying the vendor-supplied service file directly, create a drop-in override:
bash
sudo systemctl edit <service-name>This creates and preserves vendor updates.
/etc/systemd/system/<service-name>.service.d/override.conf不要直接修改供应商提供的服务文件,而是创建Drop-in覆盖配置:
bash
sudo systemctl edit <service-name>这会创建,并保留供应商的更新。
/etc/systemd/system/<service-name>.service.d/override.conf3. Apply Security Options Progressively
3. 逐步应用安全选项
Add security options in stages, testing after each stage:
Stage 1: Basic isolation
ini
[Service]分阶段添加安全选项,每阶段后进行测试:
阶段1:基础隔离
ini
[Service]Filesystem protection
文件系统保护
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
ReadWritePaths=/var/lib/myapp # Add paths service needs to write
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
ReadWritePaths=/var/lib/myapp # 添加服务需要写入的路径
Basic device protection
基础设备保护
PrivateDevices=yes
Test: `sudo systemctl restart <service>` and check `journalctl -xeu <service>`
**Stage 2: Kernel and capability restrictions**
```ini
[Service]PrivateDevices=yes
测试:`sudo systemctl restart <service>`并检查`journalctl -xeu <service>`
**阶段2:内核与权限限制**
```ini
[Service]Kernel protection
内核保护
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectKernelLogs=yes
ProtectControlGroups=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectKernelLogs=yes
ProtectControlGroups=yes
Remove capabilities
移除权限
NoNewPrivileges=yes
CapabilityBoundingSet=
Test again.
**Stage 3: Network and system call filtering**
```ini
[Service]NoNewPrivileges=yes
CapabilityBoundingSet=
再次测试。
**阶段3:网络与系统调用过滤**
```ini
[Service]Network restrictions (adjust for service needs)
网络限制(根据服务需求调整)
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
System call filtering
系统调用过滤
SystemCallFilter=@system-service
SystemCallArchitectures=native
SystemCallFilter=@system-service
SystemCallArchitectures=native
Memory protection
内存保护
MemoryDenyWriteExecute=yes
LockPersonality=yes
Test and verify functionality.MemoryDenyWriteExecute=yes
LockPersonality=yes
测试并验证功能。4. Handle Common Restriction Failures
4. 处理常见的限制失败问题
If the service fails after adding restrictions:
Error: "Permission denied" accessing filesystem
- Add the path to or relax
ReadWritePaths=toProtectSystem=instead offullstrict
Error: "Operation not permitted" for network operations
- Check includes needed protocols
RestrictAddressFamilies= - For Unix domain sockets, add
AF_UNIX
Error: System call blocked
- Review for blocked syscall name
journalctl - Add exception:
SystemCallFilter=@system-service <syscall-name>
Error: Cannot access devices
- Add specific device to instead of removing
DeviceAllow=PrivateDevices=
如果添加限制后服务失败:
错误:"Permission denied"(文件系统访问被拒绝)
- 将路径添加到,或将
ReadWritePaths=从ProtectSystem=放宽为strictfull
错误:"Operation not permitted"(网络操作被禁止)
- 检查是否包含所需协议
RestrictAddressFamilies= - 对于Unix域套接字,添加
AF_UNIX
错误:系统调用被阻止
- 查看获取被阻止的系统调用名称
journalctl - 添加例外:
SystemCallFilter=@system-service <syscall-name>
错误:无法访问设备
- 使用添加特定设备,而非移除
DeviceAllow=PrivateDevices=
5. Verify Hardening
5. 验证加固效果
After applying all restrictions:
bash
undefined应用所有限制后:
bash
undefinedCheck security score (lower is better)
检查安全评分(分数越低越好)
systemd-analyze security <service-name>
systemd-analyze security <service-name>
Verify service functionality
验证服务功能
sudo systemctl restart <service-name>
sudo systemctl status <service-name>
sudo systemctl restart <service-name>
sudo systemctl status <service-name>
Test application-level functionality
测试应用级功能
(Make requests, check logs, verify operations)
(发送请求、检查日志、验证操作)
undefinedundefinedBest Practices
最佳实践
Service Type Selection
服务类型选择
- Prefer for services that can implement sd_notify protocol - provides reliable startup verification
Type=notify - Use for standard long-running processes - good error detection
Type=exec - Avoid - provides no startup verification and poor error handling
Type=simple - Avoid - deprecated pattern, use
Type=forkingorType=notifyinsteadType=exec
- 优先使用:适用于支持sd_notify协议的服务,提供可靠的启动验证
Type=notify - 使用:适用于标准长期运行进程,错误检测能力良好
Type=exec - 避免使用:无启动验证,错误处理能力差
Type=simple - 避免使用:已弃用模式,改用
Type=forking或Type=notifyType=exec
Dependency Management
依赖管理
- Separate ordering from requirements: Use both and
After=/Requires=Wants=- controls startup sequence
After= - /
Requires=controls dependency relationshipsWants=
- Use for soft dependencies (tolerate failures)
Wants= - Use for hard dependencies (fail if dependency fails)
Requires= - For network services: Always include and
After=network-online.targetWants=network-online.target
- 将启动顺序与依赖关系分离:同时使用和
After=/Requires=Wants=- 控制启动顺序
After= - /
Requires=控制依赖关系Wants=
- 软依赖使用:可容忍依赖失败
Wants= - 硬依赖使用:依赖失败则本服务也会失败
Requires= - 网络服务:务必包含和
After=network-online.targetWants=network-online.target
Security Hardening
安全加固
- Use unless the service needs a specific user
DynamicUser=yes - Start with maximum restrictions and relax selectively - more effective than progressive hardening
- Separate secrets from configuration - use for sensitive values
EnvironmentFile= - Always set to prevent privilege escalation
NoNewPrivileges=yes - Remove all capabilities by default with , add back only what's needed
CapabilityBoundingSet= - Use to verify hardening effectiveness
systemd-analyze security
- 使用:除非服务需要特定用户
DynamicUser=yes - 从最严格的限制开始,选择性放宽:比逐步加固更有效
- 将敏感信息与配置分离:使用存储敏感值
EnvironmentFile= - 务必设置:防止权限提升
NoNewPrivileges=yes - 默认移除所有权限:使用,仅添加必要的权限
CapabilityBoundingSet= - 使用:验证加固效果
systemd-analyze security
Filesystem Access
文件系统访问
- Prefer with explicit
ProtectSystem=strictwhitelistReadWritePaths= - Always enable unless sharing /tmp is explicitly required
PrivateTmp=yes - Enable unless home directory access is needed
ProtectHome=yes - Create dedicated directories under for application data
/var/lib/
- **优先使用**搭配显式的
ProtectSystem=strict白名单ReadWritePaths= - 务必启用:除非明确需要共享/tmp
PrivateTmp=yes - 启用:除非需要访问主目录
ProtectHome=yes - 在下创建专用目录存储应用数据
/var/lib/
Restart and Recovery
重启与恢复
- Web applications: with
Restart=on-failureRestartSec=10 - Critical workers: with
Restart=alwaysRestartSec=5 - Set reasonable timeouts: and
TimeoutStartSec=30(adjust based on application)TimeoutStopSec=30 - Define custom success codes with if application uses non-zero exits for success
SuccessExitStatus=
- Web应用:搭配
Restart=on-failureRestartSec=10 - 关键工作进程:搭配
Restart=alwaysRestartSec=5 - 设置合理的超时时间:和
TimeoutStartSec=30(根据应用调整)TimeoutStopSec=30 - 自定义成功退出码:如果应用使用非零退出码表示成功,使用定义
SuccessExitStatus=
Logging and Debugging
日志与调试
- Use structured logging: and
StandardOutput=journalStandardError=journal - Set for easier log filtering
SyslogIdentifier= - Debug with: (shows extended info and follows)
journalctl -xeu <service> - Check dependencies:
systemctl list-dependencies <service>
- 使用结构化日志:和
StandardOutput=journalStandardError=journal - 设置:便于日志过滤
SyslogIdentifier= - 调试命令:(显示扩展信息并实时跟踪)
journalctl -xeu <service> - 检查依赖:
systemctl list-dependencies <service>
Resources
资源
references/systemd_options.md
references/systemd_options.md
Comprehensive reference documentation for all systemd unit and service options. Read this file when:
- Looking up specific option syntax or behavior
- Understanding security/sandboxing options in detail
- Reviewing all available service types and their tradeoffs
- Finding additional hardening options beyond the templates
Use grep to search for specific options:
bash
grep -i "ProtectSystem" references/systemd_options.md包含所有systemd单元和服务选项的综合参考文档。在以下场景中阅读该文档:
- 查找特定选项的语法或行为
- 详细了解安全/沙箱选项
- 查看所有可用的服务类型及其优缺点
- 查找模板之外的其他加固选项
使用grep搜索特定选项:
bash
grep -i "ProtectSystem" references/systemd_options.mdassets/ Templates
assets/ 模板
Production-ready service file templates:
- : Starting point for web applications without heavy sandboxing
basic-webapp.service - : Fully hardened web application with maximum security
hardened-webapp.service - : Queue processor or background daemon with security hardening
background-worker.service - : One-time initialization script pattern
oneshot-init.service
Use these as starting points and customize for specific application needs.
生产环境就绪的服务文件模板:
- :无重度沙箱的Web应用起点
basic-webapp.service - :具备最高安全级别加固的Web应用
hardened-webapp.service - :具备安全加固的队列处理器或后台守护进程
background-worker.service - :一次性初始化脚本模式
oneshot-init.service
将这些模板作为起点,根据具体应用需求进行自定义。
Common Troubleshooting
常见故障排查
Service fails to start after hardening:
- Check logs:
journalctl -xeu <service> - Look for "Permission denied" or "Operation not permitted" errors
- Identify the blocked operation (filesystem, syscall, network)
- Selectively relax the relevant restriction
- Retest and verify
Service starts but behaves incorrectly:
- Verify is correct
WorkingDirectory= - Check environment variables are loaded ()
EnvironmentFile= - Verify filesystem paths are accessible ()
ReadWritePaths= - Check user/group has appropriate permissions on files
Service restarts repeatedly:
- Check logs for crash reason:
journalctl -xeu <service> - Verify path is correct and executable
ExecStart= - Check if application crashes due to missing dependencies
- Consider increasing to prevent rapid restart loops
RestartSec= - Check if matches application behavior
Type=
Cannot access network after hardening:
- Verify includes required protocols (IPv4:
RestrictAddressFamilies=, IPv6:AF_INET, Unix sockets:AF_INET6)AF_UNIX - Check if firewall or network namespace is blocking access
- For localhost-only services, ensure is included
AF_INET
加固后服务无法启动:
- 查看日志:
journalctl -xeu <service> - 查找"Permission denied"或"Operation not permitted"错误
- 识别被阻止的操作(文件系统、系统调用、网络)
- 选择性放宽相关限制
- 重新测试并验证
服务启动但行为异常:
- 验证是否正确
WorkingDirectory= - 检查环境变量是否已加载()
EnvironmentFile= - 验证文件系统路径是否可访问()
ReadWritePaths= - 检查用户/用户组对文件是否有适当的权限
服务反复重启:
- 查看日志排查崩溃原因:
journalctl -xeu <service> - 验证路径是否正确且可执行
ExecStart= - 检查应用是否因缺少依赖而崩溃
- 考虑增加以防止快速重启循环
RestartSec= - 检查是否与应用行为匹配
Type=
加固后无法访问网络:
- 验证是否包含所需协议(IPv4:
RestrictAddressFamilies=,IPv6:AF_INET,Unix套接字:AF_INET6)AF_UNIX - 检查防火墙或网络命名空间是否阻止访问
- 对于仅本地访问的服务,确保包含
AF_INET