systemd service file generator
You’ve got a command. You want it to run as a real service, the kind systemd babysits. Fill in what to run, who runs it, how it should come back after a crash. Out comes a complete .service unit file and the exact commands to install it. Want it on a schedule instead, cron-style? Flip the timer on. All of it happens right here in your browser.
What a systemd service file generator does
On pretty much any Linux box you’ll touch today, systemd is the thing that starts your services, stops them, and drags them back up when they die. To get your own program in on that, you write a unit file. It says what the command is, who runs it, when it kicks off, what happens when it falls over. The syntax isn’t big. It’s just touchy. Forget an absolute path and the thing fails without much of a peep. Same if you pick the wrong Type or skip a daemon-reload. So this generator takes plain fields and spits out a unit file that’s actually correct, plus the commands to drop it in place.
Three sections, that’s the whole shape of a unit file. [Unit] is the metadata and the ordering bits (Description, After, Wants). [Service] is where the real work lives: the command in ExecStart, the Type, the User, the restart policy. [Install] tells systemd what “enable this” actually means, almost always WantedBy=multi-user.target so it fires at boot. Nail those, and honestly your program just sits there next to nginx and sshd like it always belonged.
Choosing the right Type
| Type | Use when |
|---|---|
simple | Your command stays in the foreground, and that process is the service. What most apps want. |
exec | Same idea as simple, but systemd holds off on calling it “started” until the binary’s actually run. A bit stricter. Solid pick on newer systemd. |
forking | The command forks, the parent quits. That’s the old-school daemon dance. You’ll usually need a PIDFile. |
oneshot | Runs, finishes, done. Often you’d bolt a timer onto it. Toss in RemainAfterExit=yes if it leaves some state behind. |
notify | The service pings systemd through sd_notify to say it’s ready. Only some things speak this, modern web servers among them. |
Restart policy and security
Restart=on-failure brings the service back if it exits non-zero or crashes. That’s the one most things should use. always goes further and restarts even on a clean exit, which fits a daemon that’s never supposed to stop. Either way, set RestartSec too, or a crashing service will just hammer itself in a loop. On the security side: don’t run it as root if you can help it. Give it a dedicated User, point it at a WorkingDirectory. And once the plain unit boots fine, I’d layer on the sandboxing directives, NoNewPrivileges=true and friends like ProtectSystem=strict or PrivateTmp=true. Maybe overkill for a throwaway script, but on anything real it’s cheap insurance.
Services, timers and cron
A systemd timer is basically cron, redone. The trick is you take a oneshot service and pair it with a .timer unit carrying an OnCalendar line. Same concept as a cron schedule, just gentler to read (daily, or *-*-* 03:00:00). And timers can do things cron can’t. Everything lands in the journal so you can actually see what ran. They’ll catch up a run you missed while the box was off, if you set Persistent=true. Plus they get all the dependency and sandboxing machinery that services already have. Tick the timer box up top and you get both files.
Privacy and how this tool runs
The whole thing runs on JavaScript, in your browser. Nothing you type leaves the page, nothing gets logged anywhere. Worth knowing, because unit files tend to be full of internal paths and service names you’d rather keep to yourself.
Frequently asked questions
Where do I put the service file?
Your own units live in /etc/systemd/system/yourname.service. Made one, or just edited it? Run sudo systemctl daemon-reload first so systemd actually re-reads what’s there. Then sudo systemctl enable --now yourname starts it and wires it up for boot in one go.
Why does my service fail with status 203/EXEC?
203/EXEC is systemd telling you it couldn’t run the command at all. Nine times out of ten it’s a path in ExecStart that isn’t absolute, so write it out in full, /usr/bin/node and so on. Or the file isn’t marked executable. Or the User you picked just can’t run it. Pull up systemctl status and journalctl -u yourname and the real reason’s usually sitting right there.
What is the difference between enable and start?
start runs it right now, this second. enable is about boot: it drops the WantedBy symlink so the thing comes up on its own next time. People mix these up constantly. enable --now just does both at once. And disable yanks the boot symlink but leaves whatever’s already running alone.
How do I pass environment variables?
Drop one or more Environment=KEY=VALUE lines into the [Service] section. The generator does that part for you. But once you’ve got a pile of them, or anything secret, switch to EnvironmentFile=/etc/yourname.env. That keeps the values out of the unit file, in a place you can lock down properly. Putting a password straight into the unit is just asking for trouble later.
Should I use a timer or cron?
If you’re already on systemd, I’d just reach for a timer. You get journal logs, catch-up on missed runs, and all the service stuff like User and sandboxing comes along for free. That said, cron isn’t dead. It’s perfectly fine for a quick recurring job, and it travels better to boxes that don’t run systemd at all. The generator hands you both the service and a matching timer, so you don’t have to choose blind.
Do I need WantedBy=multi-user.target?
Only if you actually want it up at boot. multi-user.target is the ordinary state a server sits in: multiple users, networking on, no desktop. Leave out the [Install] section entirely and you can still start the service by hand, it just won’t come up on its own. Timers are the same idea but aim at timers.target instead.
Sources & further reading
Related tools and resources
A service rarely lives alone. Sooner or later it needs a schedule, an archive job or sane file permissions, and these handle that part.













