Oneshot Startup Script

Build a systemd oneshot service for running initialization scripts at boot. Learn about RemainAfterExit, ordering with Before/After, and how oneshot differs from simple services.

Simple Services

Detailed Explanation

Running Scripts Once with systemd

The Type=oneshot service type is designed for processes that perform a task and then exit. Unlike simple services, systemd waits for the process to complete before considering the service "started."

[Unit]
Description=System Initialization Script
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/opt/scripts/initialize.sh
RemainAfterExit=yes
StandardOutput=journal
StandardError=journal
User=root

[Install]
WantedBy=multi-user.target

RemainAfterExit

The RemainAfterExit=yes directive is key for oneshot services. Without it, the service status would show "inactive (dead)" after the script completes, making it confusing to determine if it ran successfully. With this setting:

  • After the script exits with code 0, the service shows as active (exited)
  • Other services that depend on this one can verify it completed
  • systemctl is-active myinit.service returns "active"

Network Dependency

Note the use of network-online.target instead of network.target:

  • network.target: Network interfaces are configured, but may not have an IP yet
  • network-online.target: Network is fully operational with connectivity

If your script needs to download files, make API calls, or connect to remote services, use network-online.target with Wants=.

Multiple ExecStart Lines

Oneshot services uniquely allow multiple ExecStart= directives. They run sequentially:

[Service]
Type=oneshot
ExecStart=/opt/scripts/step1-setup-dirs.sh
ExecStart=/opt/scripts/step2-download-config.sh
ExecStart=/opt/scripts/step3-apply-migrations.sh

If any step fails (non-zero exit), subsequent steps are skipped and the service enters a failed state.

Ordering with Other Services

Oneshot services are commonly used as initialization gates:

[Unit]
Description=Database Migration
After=postgresql.service
Before=myapp.service
Requires=postgresql.service

This ensures migrations run after PostgreSQL starts but before the application starts.

Use Case

Running database migrations, creating required directories, downloading configuration from a remote source, or any initialization task that must complete before other services start.

Try It — Systemd Unit File Generator

Open full tool