systemd Service & Timer Generator
Fill in the form and copy a unit file, an optional timer and the commands to enable it. Use it to keep your own program running after a reboot, or to replace a cron job with a timer that logs to the journal. Everything runs in your browser; nothing is sent anywhere.
myapp.service
Enable it
How it works
- Where files go. Units you write yourself live in
/etc/systemd/system/. After saving or changing one, runsudo systemctl daemon-reload. - Service with a timer. When you add a timer, the service has no
[Install]section and you enable the timer. systemd starts the service of the same name at the scheduled time. UseType=oneshotfor jobs that run and exit. - OnCalendar uses systemd's own format (
DayOfWeek Year-Month-Day Hour:Minute:Second), not cron's. Test an expression withsystemd-analyze calendar "..."; it prints the normalised form and the next run. For the crontab equivalent, use the cron builder. - Persistent=true makes a timer catch up after downtime, which cron can't do. RandomizedDelaySec spreads the start so many servers don't hit a backup target at the same second.
- Restart policy.
on-failurerestarts after a crash or non-zero exit, not after a clean stop.alwaysalso restarts after a clean exit. Repeated fast failures eventually hit systemd's start limit and it stops trying; seesystemctl status. - ExecStart is not a shell. Use an absolute path, no pipes or redirects. For those, run
/bin/sh -c '...'. A literal%is written as%%, which the generator does for you.
Hardening, and its limits
The ticked options are a reasonable starting point for a plain program running as its own user. Check what's left with systemd-analyze security <name>.service and tighten from there. Some options will break things: ProtectSystem=strict needs every directory the program writes to listed (or use the data directory), ProtectHome hides /home, and dropping all capabilities stops it binding ports below 1024. Turn on one at a time if something fails, and read the errors in journalctl -u <name>.
This is aimed at ordinary programs. A unit that just runs docker compose needs the Docker socket, so most of these options don't apply. Containers have their own limits; the Compose generator sets memory ceilings per container.
Related
Create the user and lock down SSH first: the first 15 minutes on a fresh VPS. A backup timer pairs well with restic, and the backup planner sizes the repository. Open the right ports with the firewall generator.