The smallest useful systemd service: run one program at boot, restart it if it dies, and manage it with systemctl. This is the base every other service recipe builds on.
The unit
Save as /etc/systemd/system/myapp.service:
[Unit]
Description=My application
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/local/bin/myapp --port 8080
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
Type=simple(the default) meansExecStartis the main process and systemd considers the service started as soon as it forks. UseType=execon modern systemd for slightly stricter start semantics.ExecStart=must be an absolute path (no$PATHlookup). Pass arguments on the same line.WantedBy=multi-user.targetis what makesenablehook it into boot (the normal non-graphical “system is up” target).
Enable and start
sudo systemctl daemon-reload
sudo systemctl enable --now myapp.service
enable --now does both: start it now and start it on every boot. (enable alone only sets the boot link; start alone only runs it this once.)
Check it
systemctl status myapp.service
journalctl -u myapp.service -f
Anything your program writes to stdout/stderr is captured by the journal automatically — no need to redirect to a log file.
Gotchas: if the program forks into the background itself (an old-style daemon), use Type=forking and set PIDFile=. If it talks to the network, keep After=/Wants=network-online.target so it doesn’t start before the network is up. After any edit to the file, run systemctl daemon-reload before restart.