systemd Unit Generator
Draft a systemd service unit from command, account, restart, dependency, and hardening choices with directive notes and host install checks.- {{ err }}
{{ unitFileText }}
| Section | Directive | Value | Rationale | Copy |
|---|---|---|---|---|
| {{ row.section }} | {{ row.directive }} | {{ row.value || '-' }} | {{ row.rationale }} |
| Step | Command | Purpose | Copy |
|---|---|---|---|
| {{ row.step }} | {{ row.command }} |
{{ row.purpose }} |
| Severity | Check | Note | Copy |
|---|---|---|---|
| {{ row.severity }} | {{ row.check }} | {{ row.note }} |
Introduction
A command that behaves in a terminal can fail under systemd for reasons that have nothing to do with the application code. The service manager does not inherit a login shell, an operator's working directory, shell aliases, or temporary environment variables. It starts a named unit with a chosen account, a startup order, a readiness rule, restart policy, logging identity, and optional sandbox restrictions.
A service unit is the file that records those decisions. It tells systemd which process to start, how to judge startup, what should happen after an exit, where the process may run, which target can enable it, and what operators should inspect in status output and journal logs. That makes the unit file part launcher, part supervision policy, and part operations handoff.
Most custom units start at a deployment boundary. A background worker should survive logout, a web API should start after reboot, a Docker Compose stack needs a manager-owned lifecycle, or a maintenance command should run as a one-shot service before it is paired with a timer. The same question appears when a cron job, shell script, or manually started daemon needs predictable start, stop, restart, and inspection commands.
| Term | Meaning | Why it changes the result |
|---|---|---|
ExecStart |
The command systemd invokes as the main service command. | Absolute paths avoid surprises from missing shell search paths. |
Type |
The rule for deciding when startup has begun or completed. | exec, notify, forking, and oneshot fit different process models. |
Restart |
The policy for starting the service again after an exit or failure. | on-failure is often safer during validation than restarting every clean exit. |
WantedBy |
The target that receives the enable-time relationship. | System services commonly use multi-user.target; user services often use default.target. |
A valid-looking unit can still fail because the account is missing, the working directory is unreadable, the network wait service is not enabled, a daemon forks without a usable PID file, or hardening blocks a write path, device, kernel feature, or runtime behavior. The reliable path is to draft the unit, review every directive, verify the file on the target host, reload the manager, start the service, then prove the workload through status output, logs, and the application's own side effect.
How to Use This Tool:
Build the service from the command outward, then use the directive ledger and review notes to catch host-specific assumptions before copying the unit file.
- Choose
Service preset.Node worker,Python worker, andGo binarystart from foreground service patterns.Docker Compose appdisables hardening for compatibility.One-shot maintenance jobusesType=oneshotandRestart=no. - Enter
Service nameandDescription. The filename preview normalizes spaces and unsafe characters before adding the.servicesuffix. - Fill
ExecStart,Run as user, andWorking directory. Use absolute paths unless the target host is deliberately configured to resolve commands another way. - Set
Service type,Restart policy,Restart delay,Startup dependency,Hardening profile, andInstall target. Summary badges show the selected type, restart rule, hardening profile, and directive count. - Open
Advancedfor real needs only:Group, inline environment rows,EnvironmentFile, reload and stop commands,PIDFile, timeouts, managed directories, writable paths, orSyslogIdentifier. - Fix red validation messages before copying. Missing
Service name, missingExecStart, invalid option choices, or malformed environment rows block a ready draft. - Read
Directive Ledgerto see why each directive was emitted, then readReview Notesfor root-user, relative-path, strict-hardening, forking-PID, network-online, container-runtime, JIT-runtime, and inline-secret warnings. - Use
Install Checkliston the target host, then confirmsystemctl statusandjournalctl -fubefore treating the service as operational.
Do not put passwords, tokens, or private keys in inline environment rows. Generated text, copied tables, JSON, CSV, DOCX, and downloaded unit files can preserve those values.
Interpreting Results:
The service file is the main artifact, but the confidence cues are in the surrounding review. Red validation errors mean the current draft is not ready to copy. Yellow or review-level notes usually mean the unit can be written, but the target host or workload needs a specific check.
| Result area | What it tells you | Next check |
|---|---|---|
Service Unit |
The complete unit text grouped into [Unit], [Service], and [Install]. |
Read the command, account, directory, dependency, hardening, and install target lines before installing. |
Directive Ledger |
A row-by-row explanation of emitted directives and their rationale. | Look for preset-added hardening, restart, directory, and environment directives. |
Install Checklist |
The host-side sequence for writing, verifying, reloading, enabling, checking status, and following logs. | Run it in a test shell or maintenance window rather than pasting into production without review. |
Review Notes |
Validation errors, warnings, lower-risk review prompts, and ready status. | Fix errors first, then decide whether each warning is acceptable on the target host. |
JSON |
A structured record of inputs, generated text, directive rows, install steps, and review notes. | Use it for handoff only after removing sensitive environment values. |
A Ready to verify badge does not mean the service is installed or running. It means the current draft has no blocking input error and no high-risk warning from the page. The real proof remains systemd-analyze verify, a manager reload, a start attempt, status output, journal logs, and application-specific evidence on the target host.
Technical Details:
Service units use the same broad unit-file syntax as other systemd objects, but the service-specific section defines the process contract. [Unit] names the unit and declares relationships with other units. [Service] controls the process, identity, environment, restart behavior, timeouts, managed directories, and sandboxing. [Install] supplies the enable-time relationship used by systemctl enable.
Ordering and dependency are not the same thing. After=network-online.target changes the order if the target is part of the transaction. Wants=network-online.target pulls that target into the transaction without making it a hard requirement. That distinction is why units that truly need configured network connectivity often pair both directives, and why adding only an ordering line may not start the wait target by itself.
Rule Core:
The output is a rule-table transformation rather than a numeric calculation. Optional directives appear only when a selected policy or filled field calls for them.
| Section | Directive family | Purpose | Review boundary |
|---|---|---|---|
[Unit] |
Description=, Wants=, After= |
Names the service and sets optional startup relationship with a network target. | After= controls order only; Wants= pulls the target into the start job. |
[Service] |
Type=, ExecStart=, User=, Group=, WorkingDirectory= |
Defines the main process, readiness model, run-as identity, and starting directory. | Absolute command and directory paths reduce shell-dependent failures. |
[Service] |
Restart=, RestartSec=, TimeoutStartSec=, TimeoutStopSec= |
Controls restart decisions and start or stop wait bounds. | Restart=always can hide repeated crashes during early validation. |
[Service] |
Environment=, EnvironmentFile=, StateDirectory=, RuntimeDirectory=, ReadWritePaths= |
Provides process variables and controlled writable locations. | Inline environment values are copied into generated artifacts; secret-bearing values belong in a protected host file. |
[Service] |
NoNewPrivileges=, PrivateTmp=, ProtectSystem=, ProtectHome=, and stricter sandbox directives |
Reduces privilege gain, filesystem reach, device access, kernel access, and writable executable memory where selected. | Strict profiles need explicit writable paths or managed directories for services that write state, cache, sockets, logs, or PID files. |
[Install] |
WantedBy= |
Creates the enable-time relationship from a target to the service. | multi-user.target fits many system services; user services usually use a user-manager target. |
Service Type Semantics:
Type= changes when systemd considers startup begun or complete. That affects follow-up ordering, status interpretation, and the warnings that matter during review.
| Type | Meaning | Common fit | Caution |
|---|---|---|---|
exec |
Startup waits until the main executable has been invoked. | Foreground workers, APIs, and most modern long-running custom services. | It catches missing executable setup better than simple, but it does not prove app-level readiness. |
simple |
Startup is considered begun soon after the service process is forked. | Small services where follow-up units do not depend on executable setup being proven. | Later jobs may continue even when the command cannot be invoked as expected. |
notify |
The service reports readiness through systemd notification support. | Daemons built to send an explicit readiness signal. | Use it only when the process really sends that signal. |
forking |
The original process exits after starting a child daemon. | Legacy daemons that still daemonize themselves. | A PIDFile= is usually needed so the main process can be tracked reliably. |
oneshot |
The command runs to completion rather than staying alive. | Maintenance actions, setup jobs, and services later paired with timers. | Restart=always is rarely the right pattern for a finite job. |
Hardening profiles add service-level restrictions in increasing strength. The standard profile adds NoNewPrivileges=yes, PrivateTmp=yes, ProtectSystem=full, and ProtectHome=read-only. The network-service profile adds device and socket-family restrictions. Strict and locked-down profiles use ProtectSystem=strict and stronger kernel, cgroup, memory, clock, hostname, realtime, and system-call architecture limits. Those limits are useful only when the service can still read, write, execute, and communicate exactly as its workload requires.
Worked Examples:
Foreground worker
A Node worker using example-worker.service, ExecStart=/usr/bin/node /var/www/example/current/worker.js, User=www-data, WorkingDirectory=/var/www/example/current, Type=exec, Restart=on-failure, and RestartSec=5s produces a normal long-running service file. The review notes may still remind you that network-online.target matters only when the host's network-wait service is enabled.
One-shot maintenance command
The One-shot maintenance job preset uses daily-maintenance.service, Type=oneshot, Restart=no, and ExecStart=/usr/local/sbin/daily-maintenance. That shape fits a finite maintenance command or the service half of a later timer setup. If the restart policy changes to always, Review Notes warns that continuous restart is rarely the intended maintenance pattern.
Forking daemon repair
A legacy daemon with Service type set to forking and an empty PIDFile still generates service text, but the review warns that the main process may be hard to identify. Add a path such as /run/example-worker.pid, then verify that the daemon writes that file. If ExecStart is blank too, the red validation message must be fixed before copying.
Strict hardening with writes
A strict or locked-down service without StateDirectory, RuntimeDirectory, or ReadWritePaths receives a filesystem sandbox warning. Add managed directories or explicit writable paths when the process needs state, sockets, PID files, cache files, or logs outside the journal.
FAQ:
Does this install or enable the service?
No. It generates unit text and an install checklist. Writing the file, running verification, reloading the manager, enabling, starting, and reading logs still happen on the Linux host.
Why is Type=exec a common default?
exec waits until the executable has been invoked, so missing binary and missing user failures are surfaced earlier than with simple. It still does not prove the application is fully ready.
Should every network service use network-online.target?
No. Use network-online.target only when configured network connectivity must exist before startup and the host has the corresponding wait service enabled. Some services only need network.target, and some need no network ordering at all.
Why are inline secrets discouraged?
Inline values become part of generated unit text, copied tables, downloads, and JSON. Put passwords, tokens, and keys in a protected EnvironmentFile on the host when the service needs them.
What should I do when validation fails?
Fix the red message first. The usual blockers are a missing service name, missing ExecStart, invalid option value, or environment row that is not valid KEY=value text.
Why does strict hardening need writable paths?
ProtectSystem=strict makes most of the filesystem read-only for the service. Add StateDirectory, RuntimeDirectory, or ReadWritePaths when the process needs to write state, sockets, PID files, cache files, or logs outside the journal.
Glossary:
- Unit
- A named object managed by systemd, such as a service, timer, socket, mount, or target.
- Service unit
- A unit type that starts and supervises service processes.
- Target
- A synchronization or grouping point such as
multi-user.targetordefault.target. ExecStart- The command line systemd invokes as the main service command.
Type- The service readiness model used for startup ordering and status interpretation.
- Restart policy
- The rule that decides whether systemd should start the service again after an exit or failure.
- Hardening directive
- A service setting that restricts privileges, filesystem access, devices, kernel controls, memory behavior, or other runtime capabilities.
WantedBy- An install setting that creates the enable-time relationship from a target to the service.
References:
- systemd.service, freedesktop.org.
- systemd.unit, freedesktop.org.
- systemd.exec, freedesktop.org.
- systemd-analyze, freedesktop.org.
- How to create a systemd service unit, Simplified Guide.
- How to create a user systemd service unit, Simplified Guide.