> ## Documentation Index
> Fetch the complete documentation index at: https://docs.microsandbox.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Booting under systemd

> Hand PID 1 to systemd inside the guest so services run under a real init

By default the microsandbox agent is PID 1. That's enough for one-shot processes, but anything that calls into `systemctl`, `loginctl`, or expects a session bus will fail.

`--init auto` hands PID 1 over to systemd. The rest of the guest then behaves like a normal Linux box.

## Use systemd

<Steps>
  <Step title="Boot">
    <CodeGroup>
      ```bash macOS & Linux theme={null}
      msb run ghcr.io/superradcompany/debian-systemd:12 \
        --memory 1G --cpus 2 \
        --init auto \
        -- bash
      ```

      ```powershell Windows theme={null}
      msb run ghcr.io/superradcompany/debian-systemd:12 `
        --memory 1G --cpus 2 `
        --init auto `
        -- bash
      ```
    </CodeGroup>

    `debian-systemd` is one of the optional bases we maintain in [guest-images](https://github.com/superradcompany/guest-images) for cases like this. `--init auto` uses a known init from the image ENTRYPOINT when one is declared, then falls back to probing common distro paths. Image-declared `/init` wrappers keep their OCI launch contract for attached `msb run`; bare systemd images still run your trailing command through agentd after boot. See [Custom init system](/sandboxes/bootstrap#custom-init-system) for the exact behavior and for pinning to an explicit path.
  </Step>

  <Step title="Confirm systemd is PID 1">
    ```bash theme={null}
    root@msb:/# systemctl status
    ● msb
        State: running
        Units: 113 loaded (incl. loaded aliases)
      systemd: 252.39-1~deb12u1
    ```

    Or check directly:

    ```bash theme={null}
    root@msb:/# cat /proc/1/comm
    systemd
    ```
  </Step>

  <Step title="Manage units">
    `systemctl` works as it does on bare metal. Inspect a unit shipped with the image:

    ```bash theme={null}
    root@msb:/# systemctl status systemd-journald
    ● systemd-journald.service - Journal Service
         Loaded: loaded (/lib/systemd/system/systemd-journald.service; static)
         Active: active (running)
    ```

    Install your own and start it:

    ```bash theme={null}
    root@msb:/# apt update && apt install -y nginx
    root@msb:/# systemctl enable --now nginx
    root@msb:/# curl -s localhost | head -1
    <!DOCTYPE html>
    ```

    The guest detects microsandbox as a container, so packages with `policy-rc.d` deferral install but don't auto-start. `systemctl enable --now <unit>` starts them in one step.
  </Step>
</Steps>

## Notes

* **Image choice matters.** Distroless / minimal images (`python:3.13-slim`, `alpine`) don't ship a systemd init binary. `--init auto` will fail if it cannot resolve a known image ENTRYPOINT init or find a guest-side probe match. Use a systemd-equipped base or layer one in.
* **Memory budget.** systemd's idle footprint is \~50 MiB; daemons add more. Bump `--memory` if your service is hungry.
* **Other inits work.** `--init` accepts any absolute path. s6, OpenRC, runit, or a hand-rolled `/sbin/init` shell script are all fine; `auto` covers known image ENTRYPOINT inits plus common distro init paths.
