From systemd
runwisp import systemd converts .service units into runwisp.toml. A
Type=oneshot unit becomes a task that runs when the
daemon starts. Any other unit becomes a service.
Convert a unit
Section titled “Convert a unit”runwisp import systemd /etc/systemd/system/myapp.service -o runwisp.tomlrunwisp validateGiven tempoledger.service:
[Unit]Description=Tempo Ledger API
[Service]Type=simpleExecStart=/usr/local/bin/bun run startWorkingDirectory=/srv/tempoledgerUser=deployGroup=deployEnvironment=NODE_ENV=productionEnvironment=PORT=3000Restart=alwaysTimeoutStopSec=30KillSignal=SIGTERM
[Install]WantedBy=multi-user.targetyou get:
[services.tempoledger]description = "Tempo Ledger API"run = "/usr/local/bin/bun run start"working_dir = "/srv/tempoledger"graceful_stop = "30s"stop_signal = "SIGTERM"user = "deploy:deploy"
[services.tempoledger.env]NODE_ENV = "production"PORT = "3000"The name comes from the file name. A piped-in unit has no file name, so it gets a placeholder name and a note to rename it. A summary on stderr lists every unit and anything that needs a look.
If you already have a runwisp.toml, use --write instead of -o; see
Staging and promoting. All flags are
in the CLI reference.
Disable the unit
Section titled “Disable the unit”The import doesn’t stop or disable anything. If systemd and RunWisp both run the same process, you get two copies fighting over ports or queues. Disable the unit before starting it under RunWisp:
sudo systemctl disable --now myapp.service--now stops it immediately; disable keeps it from starting on boot. You can
move a few units at a time; just never leave one enabled in both. There is no
takeover for systemd units.
How the pieces map
Section titled “How the pieces map”| systemd | runwisp.toml | Notes |
|---|---|---|
Type=oneshot |
[tasks.NAME] with run_on_start = "boot" |
Runs once per boot. |
any other Type |
[services.NAME] |
See Restart= below. |
ExecStart |
run |
One command. @ - + ! prefixes are removed, with a note. |
WorkingDirectory |
working_dir |
|
User (+ Group) |
user |
Combined as user:group. The daemon must run as root to switch users. |
Environment |
env |
Every line is kept. |
EnvironmentFile |
env_file |
Only the first file; a leading - is dropped. |
TimeoutStopSec |
graceful_stop |
|
KillSignal |
stop_signal |
|
[Unit] Description |
description |
|
[Install] |
(not needed) | Services start with the daemon. See below. |
RunWisp starts services when the daemon starts. To keep one stopped at boot,
set autostart = false. For start order,
use depends_on.
What needs a human
Section titled “What needs a human”Anything that can’t be mapped gets a # TODO in the TOML and a note on the
unit’s row.
Restart=. Imported services use RunWisp’s defaultrestart, which restarts after any exit. ForRestart=on-failure, setrestart = "on_failure". A unit withRestart=no(or none) gets a note: if it should run once, make it a task.- More than one command. RunWisp runs one
runcommand. Only the firstExecStartis imported; otherExecStart,ExecStartPre,ExecStartPost, andExecStoplines are flagged. Put them into therunscript, or setup steps into a separate task. Type=notifyandType=forking. RunWisp watches the process it starts and treats it as up at once. Run the program in the foreground if you can.- Sandboxing.
ProtectSystem,PrivateTmp,NoNewPrivileges,CapabilityBoundingSet, and similar directives are dropped. The process gets more access than the unit allowed. If that matters, use a container or a restricted user. - Socket activation. Not supported. The program must open its own port.
- Template units.
%i,%I,%n, and similar are not filled in. Replace them in therunline.
Learn more
Section titled “Learn more”[services.*]- Tasks vs services
- Autostart, to run RunWisp itself under systemd
- From cron, for timers and cron jobs