basix-packages | bpm

basix / wiki / services

Introduction

By default, Basix uses the nitro init/service manager.

This is supplemented by s6' s6-log and runits chpst.

All "normal services" are written in the execline scripting language.

System services

Services are kept in /etc/sv. Symlinks to said services, when supervision of them is desired, are kept in /etc/nitro.

Usage

Most of your questions are probably answered by nitroctl(1):

NITROCTL(1)                 General Commands Manual                NITROCTL(1)

NAME
     nitroctl - control and manage services monitored by nitro

SYNOPSIS
     nitroctl [-t timeout] [-v] command services ...

DESCRIPTION
     nitroctl supports the following commands:

     list             List all services and information about them (default).
     scan, rescan     Rescan the service list from the file system.
     up, u            Request services to be up.
     down, d          Request services to be down.
     start            Request services to be up and wait for it to enter UP.
     stop             Request services to be down and wait for it to enter
                      DOWN.
     restart          Request services to be restarted and wait for it to be
                      UP again.
     fast-start       Request services to be started and wait for it to be in
                      state STARTING.
     fast-stop        Request services to be down and wait for it to be in
                      state SHUTDOWN.
     fast-restart, r  Request services to be restarted and wait for it to be
                      in state RESTART.
     ready            If services are in state STARTING, put them into state
                      UP.
     wait-up          Wait for services to be in state UP.
     wait-down        Wait for services to be in state DOWN or FATAL.
     wait-starting    Wait for services to be in state STARTING or UP or
                      ONESHOT.
     pause, cont, hup, alarm, interrupt, quit, term, kill, 1, 2
                      Send the signal to services.  The first character can be
                      used as a shortcut.
     pidof            Print PIDs of the services.
     check            Exit with status 0 if the services are running (known
                      PID)
     Reboot           Request system reboot.
     Shutdown         Request system shutdown.

     Note that requesting multiple transitions in a single invocation only
     guarantees each service has reached the target state at some point, not
     that all services are in the target state at the same time when nitroctl
     exits.  Requested service state transitions happen concurrently.

     The options are as follows:

     -t timeout       Exit after timeout seconds (as a decimal number) if the
                      target state has not been reached.  By default, the
                      timeout is infinite.

     -v               Verbose mode, print each state transition as it happens.

ENVIRONMENT
     NITRO_SOCK
             The control socket (by default: /var/run/nitro/nitro.sock) where
             nitro(8) listens for commands.

EXIT STATUS
     The nitroctl utility exits 0 on success, and >0 if an error occurs.

SEE ALSO
     nitro(8)

AUTHORS
     Leah Neukirchen <[email protected]>

Linux 7.2.12_1                 January 23, 2026                 Linux 7.2.12_1

Listing the currently supervised services

When running nitroctl with no arguments, a list of currently supervised (symlinked to /etc/nitro) services and their state is listed. Example:

(0) sagittarius ~ > doas nitroctl
UP LOG@acpid (pid 3892) (wstatus 0) 3105s
UP LOG@dhcpcd (pid 3886) (wstatus 0) 3105s
UP LOG@greetd (pid 3889) (wstatus 0) 3105s
UP LOG@mdevd (pid 3545) (wstatus 0) 3107s
UP LOG@mdevd-coldplug (pid 3549) (wstatus 0) 3107s
UP LOG@nftables (pid 3877) (wstatus 0) 3105s
UP LOG@ntpd (pid 3879) (wstatus 0) 3105s
UP LOG@seatd (pid 3883) (wstatus 0) 3105s
UP LOG@tty1 (pid 3896) (wstatus 0) 3105s
UP LOG@tty2 (pid 3899) (wstatus 0) 3105s
UP acpid (pid 3893) (wstatus 0) 3105s
UP dhcpcd (pid 3887) (wstatus 0) 3105s
UP getty@tty1 (pid 3898) (wstatus 0) 3105s
UP getty@tty2 (pid 3901) (wstatus 0) 3105s
UP greetd (pid 3922) (wstatus 0) 3103s
UP mdevd (pid 3546) (wstatus 0) 3107s
ONESHOT mdevd-coldplug (wstatus 0) 3105s
ONESHOT nftables (wstatus 0) 3105s
UP ntpd (pid 3881) (wstatus 0) 3105s
UP seatd (pid 3884) (wstatus 0) 3105s

Enabling and starting a service

"Enabling" in this context means linking it to nitros supervision directory. Without doing this, nitro won't even know the service exists.

To do so, for example:

ln -s /etc/sv/smartd /etc/nitro

After doing this, you will need to have nitro rescan its services. You may do this by running nitroctl rescan.

Enabling and starting a parameterized service

Some services may be parameterized, such as getty@ (notice the @).

What this basically means is that there's one service that takes arguments, and thus may be used to spawn several services.

To do this, enable the getty@ service, for example.

You then may symlink that to other services, such as getty@tty1 or getty@tty2.

Disabling and stopping a service

Remove its symlink, for example:

rm /etc/nitro/smartd

Run nitroctl rescan so nitro will be aware the service is gone.

Starting or stopping while supervised

Simply run nitroctl {start,stop} <service> to start or stop a service while keeping its supervision symlink.

Custom services

If an admin wishes to create their own service, they may place it in /etc/sv.

A typical service directory may follow this structure, as an incredibly simple oneshot service:

/etc/sv/nftables/
├── finish
└── setup

When a service has a setup script but no run script, nitro considers it a "oneshot" service.

If you want a long-running service, you should have a run script here that executes something similar to how you'd do with runit.

If you have a long-running service that has dependencies, there is an included need wrapper at /usr/lib/nitro/need that may be used in a long-running services setup script.

For example:

(0) sagittarius ~ > cat /etc/sv/greetd/setup
#!/bin/execlineb -P
fdmove -c 2 1
/usr/lib/nitro/need seatd

Admittedly this is a bit of a hack (what isn't?) and isn't strictly necessary, but it improves UX a bit. View the contents of that script if you're curious how this works.

Upon creating your custom service, symlink it to /etc/nitro and treat it like any other service.

If you need to run something as another user from a service, use chpst.

Reading logs

By default, you will have a LOG@ service enabled. This is an all-encompassing default logger service for every other service that does not specify its own log setup.

All services will get their own distinct directory in /var/log/<service>. An example of this directory may be:

(0) sagittarius ~ > doas ls -al /var/log/greetd
total 40
drwx------   2 root root  151 Oct 10 01:33 .
drwxr-xr-x  18 root root 4096 Oct 10 01:10 ..
-rw-r--r--   1 root root  450 Oct  9 17:53 current
-rw-r--r--   1 root root    0 Sep  7 19:53 lock
-rw-r--r--   1 root root    0 Sep 28 10:55 state

These logs are only readable by root by default.

Given s6-log is reasonably sane, these are just plaintext logs. View them however you wish.

Core system services

There are a handful of services on Basix that are considered "core" services and must be run by the init system before any "normal services" get to run. These are provided by the baseinit package and are kept in /usr/lib/nitro/scripts.

What actually starts these scripts would be /etc/sv/SYS/setup.

For the time being, these are all written in POSIX shell as they are more complex than typical "just exec it" type services. Bear with me.

I don't want to use nitro!

Remove its package and the baseinit package, disable the global services use flag, and use something else! Modifying your system is very much encouraged.

This will probably mean you have to write your own service scripts though, including core ones.