Master the art of systemd unit file configuration. This comprehensive guide covers all unit file types, syntax, directives, and best practices for creating robust systemd configurations.
What are systemd Unit Files?
Unit files are the configuration files that define how systemd should manage resources. Each unit file describes a single resource such as a service, socket, device, mount point, or timer.
- Declarative configuration: Describe what you want, not how to do it
- Standardized format: INI-style configuration files
- Multiple types: Services, sockets, timers, mounts, swaps, etc.
- Location-based: Different directories for different purposes
- Drop-in overrides: Partial configuration overrides supported
1. Unit File Types
2. Unit File Locations & Hierarchy
/etc/systemd/system//run/systemd/system//usr/lib/systemd/system//etc/systemd/system/*.d/Drop-in Directory Example
# Original unit file
/usr/lib/systemd/system/nginx.service
# System administrator override
/etc/systemd/system/nginx.service.d/custom.conf
# Drop-in file content
[Service]
Environment="NGINX_WORKER_PROCESSES=4"
LimitNOFILE=65536
RestartSec=5
3. Service Unit File Deep Dive
Complete Service Unit Example
# /etc/systemd/system/webapp.service
[Unit]
Description=Python Web Application
Documentation=https://example.com/docs
After=network.target postgresql.service
Wants=postgresql.service
Requires=network.target
Before=multi-user.target
ConditionPathExists=/opt/webapp/config.py
AssertPathIsReadWrite=/var/log/webapp
[Service]
Type=simple
User=webapp
Group=webapp
WorkingDirectory=/opt/webapp
Environment="DATABASE_URL=postgresql://localhost/webapp"
EnvironmentFile=/etc/default/webapp
ExecStart=/usr/bin/python3 /opt/webapp/app.py
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/bin/kill -TERM $MAINPID
Restart=on-failure
RestartSec=10
TimeoutStopSec=30
TimeoutStartSec=30
StartLimitInterval=100
StartLimitBurst=10
LimitNOFILE=65536
LimitNPROC=4096
StandardOutput=journal
StandardError=journal
SyslogIdentifier=webapp
# Security hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/webapp
ReadOnlyPaths=/etc/webapp
[Install]
WantedBy=multi-user.target
Alias=webapp.service
Also=webapp-socket.socket
[Unit] Section Directives
DescriptionDescription=Web Application ServerDocumentationDocumentation=man:nginx(8)AfterAfter=network.targetBeforeBefore=multi-user.targetRequiresRequires=postgresql.serviceWantsWants=network-online.targetConflictsConflicts=old-service.serviceCondition*ConditionPathExists=/etc/configAssert*AssertPathIsDirectory=/var/lib/app[Service] Section Directives
TypeType=simpleUser/GroupUser=nginxExecStartExecStart=/usr/sbin/nginxExecStopExecStop=/bin/kill $MAINPIDRestartRestart=on-failureRestartSecRestartSec=5sEnvironmentEnvironment="PORT=8080"WorkingDirectoryWorkingDirectory=/var/wwwLimit*LimitNOFILE=65536StandardOutputStandardOutput=journal4. Advanced Unit File Examples
Socket Activation Unit
# /etc/systemd/system/myapp.socket
[Unit]
Description=MyApp Socket
PartOf=myapp.service
[Socket]
ListenStream=0.0.0.0:8080
Accept=true
SocketUser=myapp
SocketGroup=myapp
SocketMode=0660
[Install]
WantedBy=sockets.target
# /etc/systemd/system/myapp@.service
[Unit]
Description=MyApp Instance %i
[Service]
ExecStart=/usr/bin/myapp --instance %i
StandardInput=socket
Timer Unit with Calendar Expressions
# /etc/systemd/system/backup.timer
[Unit]
Description=Daily backup timer
[Timer]
OnCalendar=daily
Persistent=true
RandomizedDelaySec=1h
AccuracySec=1min
Unit=backup.service
[Install]
WantedBy=timers.target
# Calendar expression examples
# OnCalendar=*-*-* 02:00:00 # Daily at 2 AM
# OnCalendar=Mon,Fri *-*-* 10:00 # Monday and Friday at 10 AM
# OnCalendar=*-*-15 00:00 # 15th of every month
# OnCalendar=*-12-25 00:00 # December 25th every year
Path Unit for File Monitoring
# /etc/systemd/system/config-watcher.path
[Unit]
Description=Monitor config file changes
[Path]
PathChanged=/etc/myapp/config.conf
PathModified=/etc/myapp/
Unit=config-reloader.service
[Install]
WantedBy=multi-user.target
# /etc/systemd/system/config-reloader.service
[Unit]
Description=Reload configuration
[Service]
Type=oneshot
ExecStart=/usr/bin/myapp --reload-config
5. Unit File Management Tools
6. Best Practices & Common Patterns
systemd-analyze verify before deploying. Check for syntax errors and undefined dependencies.
/etc/systemd/system/*.d/ for overrides.
systemctl status -l and journalctl -u for debugging. Enable debug logging with StandardOutput=journal+console.
Unit File Creation Checklist
- Use descriptive
Descriptionwith application name - Set proper dependencies (
After,Requires,Wants) - Specify
UserandGroupfor security - Set
WorkingDirectoryfor consistent paths - Configure
RestartandRestartSecfor resilience - Set appropriate resource limits (
LimitNOFILE,LimitNPROC) - Use
EnvironmentorEnvironmentFilefor configuration - Specify
ExecStopfor clean shutdown - Set
WantedByin [Install] section - Test with
systemd-analyze verify
1. Missing Type= directive: Defaults to Type=simple which may not be correct
2. Forgetting daemon-reload: Always run
systemctl daemon-reload after changes3. Absolute paths required: All paths in ExecStart must be absolute
4. Incorrect dependencies: Circular dependencies or missing requirements
5. No ExecStop: Services may not stop cleanly
6. Missing User/Group: Running as root is a security risk
7. Hardcoded values: Use environment variables for configuration
8. No resource limits: Can lead to system resource exhaustion
9. Incorrect socket permissions: Socket units need proper SocketUser/SocketGroup
10. Not testing: Always test units in a staging environment first
7. Template Units & Instance Units
Template Unit Example
# /etc/systemd/system/app@.service (Template)
[Unit]
Description=Application Instance %i
[Service]
Type=simple
User=appuser
ExecStart=/usr/bin/app --instance %i --port 80%i
Environment="INSTANCE=%i"
Restart=on-failure
[Install]
WantedBy=multi-user.target
# Create instances
systemctl start app@1.service # Instance 1, port 801
systemctl start app@2.service # Instance 2, port 802
systemctl start app@web.service # Instance "web", port 80web
Template Unit Patterns
# Common template patterns
app@%i.service # Numeric instances
app@%I.service # Instance identifier
app-%i.service # Alternative naming
app@%H.service # Hostname-based
app@%m.service # Machine ID-based
# Special specifiers
%n = full unit name # app@1.service
%N = escaped unit name # app\x401.service
%p = prefix # app
%i = instance name # 1, web, etc.
%j = removed suffix # Depends on unit type
%g = last component of %j
Getting Started with Unit Files
Follow this learning path to master systemd unit files:
- Start with services: Learn .service unit files first
- Study packaged units: Examine units from your distribution
- Create simple units: Make a basic service for a script
- Add dependencies: Learn After, Requires, Wants
- Experiment with types: Try simple, forking, oneshot
- Use drop-ins: Practice overriding packaged units
- Learn other types: Explore sockets, timers, paths
- Master templates: Create instance-based services
- Implement security: Add User, PrivateTmp, etc.
- Automate validation: Use systemd-analyze in scripts
Master systemd Unit File Configuration
systemd unit files provide a powerful, declarative way to manage system resources. By understanding the structure, directives, and best practices, you can create robust, maintainable system configurations.
Remember: Good unit files are like good code - they should be clear, maintainable, and well-documented. Use drop-ins for customizations, validate your configurations, and always test before deploying to production.
Next Steps: Start by examining existing unit files on your system. Create a simple service unit for a custom script. Experiment with socket activation and timer units. As you gain experience, you'll appreciate the flexibility and power of systemd's unit file system.