1. Home
  2. Developer tools
  3. systemd Unit Generator

systemd Unit Generator

Keep a Node, Python or Go app running after logout and reboot, or replace a cron job with a systemd timer that logs to the journal.

Free, no sign-up. Runs in your browser: nothing is uploaded.

How to use systemd Unit Generator

  1. Enter the command, working folder, user and restart policy.
  2. Optionally turn on hardening or a timer schedule.
  3. Copy the units into /etc/systemd/system and enable them.

Features

  • Type simple, exec, notify, forking or oneshot
  • Restart= and RestartSec= with network-online ordering
  • Environment= lines and EnvironmentFile=
  • Hardening: NoNewPrivileges, ProtectSystem=strict, PrivateTmp and more
  • Timers with OnCalendar=, Persistent= and a random delay

Supported formats

Input

  • Form input

You get

  • SERVICE
  • TIMER

Private by design

Everything you enter is processed by your browser on this device. Nothing is sent to openWorkstand or anyone else, so the systemd Unit Generator is safe for private and work data. After you have used it once while online, it also works without an internet connection. How local processing works

Good to know

  • Hardening options can block programs that write outside their folder; add ReadWritePaths= as needed.

Guide

Writing systemd services and timers for your own apps

On almost every modern Linux distribution, systemd starts and supervises long-running programs. A small unit file is all it takes to make your own app start at boot, restart when it crashes and log to the journal, and a matching timer can replace a cron job. This generator writes those files from a form, with sensible defaults and optional security hardening.

The anatomy of a unit file

A service unit has three sections. [Unit] describes it and declares ordering: After=network-online.target together with Wants= makes systemd start the network first. [Service] says how to run the program: its command, user, folder, environment and restart behaviour. [Install] says when to start it once enabled; WantedBy=multi-user.target means at normal boot.

Service types

simple and exec are right for programs that stay in the foreground, which covers Node, Python, Go and Java servers; exec waits until the binary has actually started before reporting success. notify is for programs that tell systemd when they are ready through sd_notify. forking is for old-style daemons that background themselves, and oneshot for commands that run to completion, such as backups. When a timer is generated, the service becomes oneshot automatically.

Restarts and environment

Restart=on-failure restarts the program when it exits with an error or is killed by a signal; always also restarts after a clean exit. RestartSec= waits between attempts so a crashing program does not spin. Each line in the environment box becomes an Environment= entry, quoted where needed, and EnvironmentFile= loads a file of KEY=value lines, which keeps secrets out of the unit file itself.

Hardening

The hardening option adds a set of sandboxing directives. NoNewPrivileges stops the process from gaining rights through setuid programs, PrivateTmp gives it its own /tmp, ProtectSystem=strict makes the whole file system read-only except for paths listed in ReadWritePaths= (the working directory is added), and ProtectHome hides home folders. These settings shrink the damage a compromised app can do, but an app that writes logs or uploads elsewhere will fail until you add those folders to ReadWritePaths=.

Timers instead of cron

A timer unit triggers a service on a calendar schedule. OnCalendar=daily runs at midnight, Mon..Fri 09:00 on weekday mornings and *:0/15 every fifteen minutes. Persistent=true runs a missed job at the next boot if the machine was off at the scheduled time, and RandomizedDelaySec=60 spreads the start by up to a minute so many machines do not hit a server at once. Every run is logged in the journal.

A worked example

With the defaults, the service file starts the Node app with ExecStart=/usr/bin/node /opt/myapp/server.js as user myapp in /opt/myapp, with Restart=on-failure, RestartSec=5, two Environment= lines, EnvironmentFile=/etc/myapp.env, the hardening block including ProtectSystem=strict, and WantedBy=multi-user.target. Ticking “Also create a .timer” switches the service to oneshot and adds a timer with OnCalendar=daily, Persistent=true and WantedBy=timers.target.

Installing and debugging

Copy the files to /etc/systemd/system/, run systemctl daemon-reload, then systemctl enable --now myapp.service (or the .timer for scheduled jobs). systemctl status myapp shows whether it is running and its last log lines, and journalctl -u myapp.service -f follows the log live. Errors such as “Executable path is not absolute” mean ExecStart needs a full path.

Checked against the current version of the systemd Unit Generator on .

Frequently asked questions

Should I run the service as root?

Almost never. Create a system user with useradd --system --no-create-home myapp, give it ownership of the app folder, and set User= and Group=. If the app needs a low port such as 80, use AmbientCapabilities=CAP_NET_BIND_SERVICE or a reverse proxy instead of root.

How do I check a timer’s next run?

systemctl list-timers shows every timer with its next and last trigger times. To test an OnCalendar expression before using it, run systemd-analyze calendar with the expression in quotes; it prints the normalised form and the next elapse time.

Why use a systemd timer instead of cron?

Timers log every run to the journal, can catch up on runs missed while the machine was off (Persistent=true), never start a second copy while one is running, and can depend on other units such as the network.

How do I see why my service fails to start?

Run systemctl status yourapp for the last lines and exit code, and journalctl -u yourapp -e for the full log. A common cause is a relative path in ExecStart; it must be absolute.

Keep working with the result

openWorkstand also includes a free workspace with documents, spreadsheets, tasks, projects and a calendar that save to a folder on your computer.