Deploying custom systemd service units, timers, and socket definitions on Ubuntu requires precision. A single typographical error in a directive name, an incorrect path to an executable binary, or a circular dependency can prevent critical daemons from starting upon boot or reload. While administrators often test units by running systemctl daemon-reload followed by systemctl start, this trial-and-error approach risks service outages on production servers. Ubuntu includes the built-in systemd-analyze verify utility, a diagnostic tool that statically parses and validates systemd unit files against active kernel security features, directory hierarchies, and dependency trees without starting the actual service.
Understanding systemd-analyze verify Capabilities
The systemd-analyze verify command performs static code analysis on one or more unit files:
- Directive Validation: Verifies that all configuration keys in the
[Unit],[Service], and[Install]sections are syntactically valid and recognized by the installed systemd version. - Binary & Path Verification: Confirms that paths specified in
ExecStart=,ExecStop=, andWorkingDirectory=exist and possess appropriate executable permissions. - Dependency Consistency: Checks for conflicting or unreachable dependencies defined in
Requires=,Wants=,After=, andBefore=. - Security Directive Checks: Audits sandbox directives (such as
ProtectSystem=,PrivateTmp=, andCapabilityBoundingSet=) for compatibility with unprivileged user execution.
Validating an Existing Service Unit
To validate a service unit that is already installed in standard system directories (such as /etc/systemd/system or /lib/systemd/system), pass the unit name as an argument:
systemd-analyze verify nginx.service
If the unit configuration is completely error-free, the command outputs nothing and exits with a status code of 0. If any warnings, syntax errors, or missing dependencies are discovered, the utility prints detailed diagnostic messages to standard error.
For example, if an obsolete or misspelled directive is present:
/etc/systemd/system/custom.service:7: Unknown key name 'RestartAlway' in section 'Service', ignoring.
Validating Offline or Uninstalled Unit Files
One of the most powerful features of systemd-analyze verify is its ability to test unit files before copying them to system paths or invoking systemctl daemon-reload. This makes it ideal for pre-commit git hooks and CI/CD validation pipelines.
To check a local unit file stored in your current project directory:
systemd-analyze verify ./my-custom-app.service
If the unit references external configuration files (such as EnvironmentFile=/etc/default/myapp) or specific executables, verify checks whether those files exist on the host filesystem and warns if they are absent.
Filtering Verification Output with Flags
By default, systemd-analyze verify inspects the targeted unit and recursively verifies all units it depends upon or pulls in via Wants= or Requires=. On a full system, this can generate noise regarding unrelated system units. You can control verification scope using flags:
- –no-man: Suppresses checks for missing man page references defined in
Documentation=directives.systemd-analyze verify --no-man ./my-custom-app.service - –recursive=no: Restricts validation strictly to the specified unit file, skipping secondary dependencies:
systemd-analyze verify --recursive=no ./my-custom-app.service - –user: Validates user-level systemd service units located in
~/.config/systemd/useror/etc/systemd/userwithin the user session context:systemd-analyze verify --user ./user-task.service
Integrating Unit Verification into CI/CD Pipelines
You can embed systemd-analyze verify into bash deployment scripts or GitHub Actions workflows to block deployment of broken service files automatically:
#!/bin/bash
set -e
UNIT_FILE="./deploy/api-gateway.service"
echo "Validating systemd unit file: $UNIT_FILE"
if systemd-analyze verify --recursive=no "$UNIT_FILE"; then
echo "Unit file syntax is valid."
sudo cp "$UNIT_FILE" /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl restart api-gateway.service
else
echo "Validation failed. Aborting deployment." >&2
exit 1
fi
Interpreting Common Verification Warnings
When reviewing verification output, pay attention to these common warning patterns:
- Executable Path Not Absolute: In systemd, binaries must be specified as absolute paths (e.g.
/usr/bin/noderather thannode), unless the systemd version explicitly supports path searching. - Special Characters in Unit Names: Dashes in service names are interpreted as instance separators in template units (e.g.
[email protected]). If a regular service contains unexpected dashes,verifyflags potential naming conflicts. - Missing Install Section: If a unit omits the
[Install]section,systemd-analyze verifywarns that the unit cannot be enabled viasystemctl enableto boot automatically.