Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Run a One-Shot Command

Before the main daemon starts, you may need to fix file ownership, run the app’s own database migrations, or perform other idempotent setup. Oneshots run to completion and block dependent daemons until they finish.

A oneshot runs on every start, so it fits work whose answer can differ next time. Work keyed to the package version — relocating or repairing data an older release left behind — belongs in migrations.up instead, even when you can guard it to be idempotent. See main.md § Choosing Between a Oneshot, an Init, and a Migration.

Solution

Use .addOneshot() in the daemon chain. Oneshots run to completion and block dependent daemons via the requires array. Use exec.command for simple shell commands (e.g., chown) or exec.fn for complex async logic. Oneshots run on every service start, not just once — they must be idempotent. A post-startup oneshot can depend on a daemon (requires: ['app']) to run after the app is healthy.

Reference: Main

Examples

See startos/main.ts in: ghost (chown-mysql), immich (configure-libraries), nextcloud (chown), btcpayserver