Table of Contents
- Understanding Systemd Service Files
- Why Override Instead of Edit?
- Methods to Override Systemd Service Defaults
- Common Override Scenarios with Examples
- Verifying and Testing Overrides
- Troubleshooting Overrides
- Best Practices
- Conclusion
- References
1. Understanding Systemd Service Files
Before overriding defaults, it helps to understand how systemd service files work. A systemd service is defined by a .service file, which contains configuration directives organized into sections (e.g., [Unit], [Service], [Install]).
Key Locations for Service Files
Systemd loads service files from three primary directories (processed in this order, with later directories overriding earlier ones):
/usr/lib/systemd/system/: Default service files provided by installed packages (e.g., fromapt,yum, ordnf). These are managed by the package manager and may be overwritten during updates./run/systemd/system/: Runtime-generated service files (temporary, not persistent across reboots)./etc/systemd/system/: User-customized service files and drop-in overrides. This is where your modifications should live, as they persist across updates and reboots.
Anatomy of a .service File
A typical .service file includes three core sections:
| Section | Purpose |
|---|---|
[Unit] | Metadata and dependencies (e.g., Description, After=, Requires=). |
[Service] | Service-specific configuration (e.g., ExecStart, User, Restart). |
[Install] | Installation settings (e.g., WantedBy=multi-user.target for enabling on boot). |
Example (nginx.service snippet):
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf
ExecReload=/bin/kill -s HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=42s
[Install]
WantedBy=multi-user.target
2. Why Override Instead of Edit?
You might be tempted to edit the original .service file directly (e.g., in /usr/lib/systemd/system/), but this is strongly discouraged. Here’s why:
- Package Updates Overwrite Changes: When you update the service’s package (e.g.,
sudo apt upgrade nginx), the package manager will replace the original.servicefile, erasing your edits. - Complexity: Tracking manual edits across multiple service files is error-prone, especially in multi-admin environments.
- Portability: Overrides in
/etc/systemd/system/are easier to back up, replicate, or version-control.
The Solution: Use drop-in configuration files to override specific settings without modifying the original service file.
3. Methods to Override Systemd Service Defaults
Systemd provides two primary methods to override service defaults: drop-in files (recommended) and interactive editing with systemctl edit.
Method 1: Drop-In Configuration Files (Recommended)
Drop-in files are partial .service files stored in a special directory structure under /etc/systemd/system/. They override specific settings while leaving the original service file intact.
Step 1: Create the Drop-In Directory
For a service named <service>.service, create a directory named <service>.service.d/ in /etc/systemd/system/:
sudo mkdir -p /etc/systemd/system/<service>.service.d/
Example for nginx:
sudo mkdir -p /etc/systemd/system/nginx.service.d/
Step 2: Create the Override File
Inside this directory, create a .conf file (e.g., override.conf or a descriptive name like custom-env.conf). The filename doesn’t matter (as long as it ends with .conf), but override.conf is conventional.
sudo nano /etc/systemd/system/<service>.service.d/override.conf
Step 3: Define Overrides in the File
In the override file, specify only the sections and parameters you want to override. For example, to change the User for a service:
[Service]
User=my_custom_user
- To clear a default value: Set the parameter to an empty string (e.g.,
Environment=to remove all default environment variables). - To append to a list: Use
+=(e.g.,Environment+=EXTRA_VAR=valueto add a new environment variable without replacing existing ones).
Method 2: Interactive Editing with systemctl edit
For a quicker workflow, use systemctl edit <service>, which automatically creates the drop-in directory and opens an editor (default: nano or vi, configurable via $EDITOR).
Example:
sudo systemctl edit nginx
This opens a temporary file that will be saved to /etc/systemd/system/nginx.service.d/override.conf when you exit the editor.
Method 3: Editing the Service File Directly (Not Recommended)
You can copy the original service file to /etc/systemd/system/ and edit it there (since /etc/ takes precedence over /usr/lib/), but this is risky:
- You’ll lose upstream updates to the service file (e.g., security fixes or configuration improvements).
- It’s harder to track which changes you’ve made.
Only use this method if you need to completely replace the service file (e.g., for a heavily customized service).
4. Common Override Scenarios with Examples
Let’s walk through practical examples of common overrides. For each scenario, we’ll use the drop-in file method.
Scenario 1: Changing the ExecStart Command
ExecStart defines the command to start the service. Overriding it lets you modify arguments, paths, or the executable itself.
Example: Run nginx with a custom configuration file.
-
Create the drop-in directory:
sudo mkdir -p /etc/systemd/system/nginx.service.d/ -
Create
override.conf:sudo nano /etc/systemd/system/nginx.service.d/override.conf -
Add the override:
[Service] # Replace the default ExecStart with a custom command ExecStart= ExecStart=/usr/sbin/nginx -c /etc/nginx/custom.conf -g 'daemon on; master_process on;'- Why
ExecStart=first? Systemd requires clearing the defaultExecStartbefore defining a new one (sinceExecStartcan only be set once per service).
- Why
Scenario 2: Setting Environment Variables
Use Environment or EnvironmentFile to pass custom environment variables to the service.
Example: Set NODE_ENV=production for a Node.js service.
Override file:
[Service]
Environment=NODE_ENV=production
Environment=API_KEY=secret_key_123
To load variables from a file (e.g., /etc/myapp.env):
[Service]
EnvironmentFile=/etc/myapp.env
Scenario 3: Modifying User/Group
By default, many services run as root. Override User and Group to run them as a non-privileged user.
Example: Run nginx as user nginx-user (instead of root).
Override file:
[Service]
User=nginx-user
Group=nginx-group
Note: Ensure the user/group exists (sudo useradd -r nginx-user) and has permissions for service files (e.g., log directories).
Scenario 4: Adjusting Restart Policy and Timeouts
Restart defines when systemd should restart the service (e.g., on failure, always). RestartSec sets the delay between restarts.
Example: Restart a service “always” with a 10-second delay.
Override file:
[Service]
Restart=always
RestartSec=10
Common Restart values:
no: Never restart (default).on-failure: Restart on non-zero exit code, signal, or timeout.always: Restart regardless of exit code (except when stopped manually).
Scenario 5: Adding Dependencies
Use After= or Requires= in the [Unit] section to ensure the service starts after other services (e.g., a database).
Example: Start a Node.js app only after postgresql is running.
Override file:
[Unit]
After=postgresql.service
Requires=postgresql.service # Fail if postgresql isn't running
After=: Ensures ordering (service starts after the listed units).Requires=: Creates a hard dependency (service fails if dependencies fail).
Scenario 6: Disabling Default Behaviors
Some services enable security features by default (e.g., PrivateTmp=yes, which isolates /tmp for the service). Override these to disable them.
Example: Disable PrivateTmp for a service that needs access to system-wide /tmp.
Override file:
[Service]
PrivateTmp=no
5. Verifying and Testing Overrides
After creating overrides, verify they’re applied correctly:
Step 1: Reload the Systemd Daemon
Systemd must reload its configuration to detect new overrides:
sudo systemctl daemon-reload
Step 2: Check Merged Configuration with systemctl cat
systemctl cat <service> shows the original service file plus all drop-in overrides merged together.
Example:
sudo systemctl cat nginx
Output will include lines like:
# /usr/lib/systemd/system/nginx.service
[Unit]
Description=The nginx HTTP and reverse proxy server
...
# /etc/systemd/system/nginx.service.d/override.conf
[Service]
User=nginx-user
This confirms your override is active.
Step 3: View Active Parameters with systemctl show
systemctl show <service> dumps all active parameters for the service. Filter with grep to check specific overrides:
Example:
sudo systemctl show nginx | grep User
Output:
User=nginx-user
Step 4: Restart the Service and Check Status
Apply the changes by restarting the service:
sudo systemctl restart nginx
Verify it’s running with your overrides:
sudo systemctl status nginx
6. Troubleshooting Overrides
If your service doesn’t start or overrides aren’t applied, check these common issues:
Issue: Override Not Detected
- Fix: Run
sudo systemctl daemon-reloadto reload configurations. - Check:
systemctl cat <service>to ensure your drop-in file is listed.
Issue: Syntax Error in Override File
- Symptom: Service fails to start, with
journalctlshowingFailed to parse configuration. - Fix: Validate the override file with
systemd-analyze verify <service>:sudo systemd-analyze verify nginx
Issue: Incorrect Section Name
- Symptom: Override has no effect (e.g.,
[Services]instead of[Service]). - Fix: Ensure section names match exactly (case-sensitive:
[Unit],[Service],[Install]).
Issue: Missing Permissions
- Symptom: Service fails with “permission denied” after changing
User. - Fix: Ensure the user has read/write access to service files (e.g., logs, configs).
Check Logs with journalctl
For detailed error messages, view the service’s logs:
sudo journalctl -u <service> -f # -f = "follow" for real-time logs
7. Best Practices
To keep overrides maintainable and safe:
- Use Drop-In Files Exclusively: Avoid editing original service files.
- Keep Overrides Minimal: Only override parameters you need to change (don’t copy entire sections).
- Name Drop-In Files Descriptively: Use names like
env-overrides.conforrestart-policy.confinstead of genericoverride.conf. - Document Changes: Add comments in override files explaining why changes were made (e.g.,
# Run as non-root for security). - Test in Staging: Validate overrides in a non-production environment before deploying.
- Version-Control Overrides: Store
/etc/systemd/system/in Git for backup and tracking.
8. Conclusion
Overriding systemd service defaults is a critical skill for customizing Linux services safely and maintainably. By using drop-in files in /etc/systemd/system/, you ensure your changes persist across updates and remain easy to manage.
Whether you’re adjusting command-line arguments, setting environment variables, or modifying dependencies, the workflow remains consistent: create a drop-in directory, define overrides, reload systemd, and verify. With these tools, you can tailor systemd services to your exact needs.