doc: convert the remaining legacy syntax

The block conversion changed the bodies of the reference sections but
left every "**Syntax:**" header spelling the line-based format, so each
page opened by teaching the format it then stopped using.  Six files
were missed entirely: runparts, files, capabilities, requirements,
runlevels, and switchroot.

runparts had no block spelling written down anywhere, though the parser
has read `runparts`, `runparts-progress`, and `runparts-sysv` all along.

tty gains a table per variant.  Its three syntax lines carried nine
positional fields between them, which no longer describes anything the
parser accepts.

Fixes #148

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg committed 2026-07-30 15:23:13 +02:00
1 parent b44a5ff2f8
commit 00794d41bc
17 files changed
+340 -173

No files matched your search

+9 -9
View File
@@ -242,16 +242,16 @@ Composition
----------- -----------
The `pid/` conditions are generated by the Finit `pidfile.so` plugin and The `pid/` conditions are generated by the Finit `pidfile.so` plugin and
composed from a service's `name:` and `:id`. By default the basename of composed from a service's block title and its `:id`. By default the
the daemon and the empty string. basename of the daemon and the empty string.
| **service** | **condition** | | **service** | **condition** |
|----------------------------------------------------|------------------| |-------------------------------------------------------------------|------------------|
| /sbin/foo | pid/foo | | `service { command = "/sbin/foo" }` | pid/foo |
| /sbin/bar -p /run/baz.pid | pid/bar | | `service { command = "/sbin/bar -p /run/baz.pid" }` | pid/bar |
| name:lxc :foo lxc-start -n foo -p /run/lxc/foo.pid | pid/lxc:foo | | `service lxc:foo { command = "lxc-start -n foo -p /run/lxc/foo.pid" }` | pid/lxc:foo |
| /usr/bin/dbus-daemon | pid/dbus-daemon | | `service { command = "/usr/bin/dbus-daemon" }` | pid/dbus-daemon |
| :222 dropbear -p 222 | pid/dropbear:222 | | `service dropbear:222 { command = "dropbear -p 222" }` | pid/dropbear:222 |
The condition is asserted when `pidfile.so` receives an inotify event The condition is asserted when `pidfile.so` receives an inotify event
for a file matching `/run/*.pid`, `/run/**/*.pid`, or `/run/**/pid`, for a file matching `/run/*.pid`, `/run/**/*.pid`, or `/run/**/pid`,
+41 -31
View File
@@ -16,14 +16,17 @@ which is the same approach used by other modern service managers like dinit.
## Basic Usage ## Basic Usage
Capabilities are specified using the `caps:` directive in service configuration: Capabilities are specified with the `capabilities` key, alias `caps`:
```conf ```conf
service [2345] name:nginx \ service nginx {
@www-data:www-data \ description = "Web server"
caps:^cap_net_bind_service \ runlevel = "2345"
/usr/sbin/nginx -g 'daemon off;' \ user = "www-data"
-- Web server group = "www-data"
capabilities = { "^cap_net_bind_service" }
command = "/usr/sbin/nginx -g 'daemon off;'"
}
``` ```
This example allows nginx to bind to privileged ports (like 80 and 443) while This example allows nginx to bind to privileged ports (like 80 and 443) while
@@ -52,7 +55,7 @@ with the following prefixes:
Multiple capabilities can be specified as a comma-separated list: Multiple capabilities can be specified as a comma-separated list:
```conf ```conf
caps:^cap_net_raw,^cap_net_admin,^cap_net_bind_service capabilities = { "^cap_net_raw", "^cap_net_admin", "^cap_net_bind_service" }
``` ```
## Common Use Cases ## Common Use Cases
@@ -62,10 +65,13 @@ caps:^cap_net_raw,^cap_net_admin,^cap_net_bind_service
Allow a web server to bind to ports 80 and 443 without running as root: Allow a web server to bind to ports 80 and 443 without running as root:
```conf ```conf
service [2345] name:webserver \ service webserver {
@www-data:www-data \ runlevel = "2345"
caps:^cap_net_bind_service \ user = "www-data"
/usr/sbin/nginx -g 'daemon off;' group = "www-data"
capabilities = { "^cap_net_bind_service" }
command = "/usr/sbin/nginx -g 'daemon off;'"
}
``` ```
### Network Monitoring (Raw Sockets) ### Network Monitoring (Raw Sockets)
@@ -73,10 +79,12 @@ service [2345] name:webserver \
Allow packet capture without root privileges: Allow packet capture without root privileges:
```conf ```conf
service [2345] name:tcpdump \ service tcpdump {
@tcpdump \ runlevel = "2345"
caps:^cap_net_raw,^cap_net_admin \ user = "tcpdump"
/usr/sbin/tcpdump -i eth0 -w /var/log/capture.pcap capabilities = { "^cap_net_raw", "^cap_net_admin" }
command = "/usr/sbin/tcpdump -i eth0 -w /var/log/capture.pcap"
}
``` ```
### NTP Daemon (System Time) ### NTP Daemon (System Time)
@@ -84,10 +92,12 @@ service [2345] name:tcpdump \
Allow time synchronization without full root: Allow time synchronization without full root:
```conf ```conf
service [2345] name:ntpd \ service ntpd {
@ntp \ runlevel = "2345"
caps:^cap_sys_time,^cap_sys_nice \ user = "ntp"
/usr/sbin/ntpd -n capabilities = { "^cap_sys_time", "^cap_sys_nice" }
command = "/usr/sbin/ntpd -n"
}
``` ```
## Available Capabilities ## Available Capabilities
@@ -116,9 +126,9 @@ Common capabilities include (see `man 7 capabilities` for the complete list):
- Don't grant `cap_sys_admin` unless absolutely necessary - Don't grant `cap_sys_admin` unless absolutely necessary
2. **Specify a user (preferably non-root)** 2. **Specify a user (preferably non-root)**
- The `@user` directive is **required** for `caps:` to take effect - The `user` setting is **required** for `capabilities` to take effect
- For ambient capabilities (`^`), use a non-root user (not `@root`) - For ambient capabilities (`^`), use a non-root user (not `"root"`)
- Example: `@www-data`, `@nginx`, `@tcpdump` - Example: `user = "www-data"`, `user = "nginx"`, `user = "tcpdump"`
3. **Use ambient capabilities (`^`)** 3. **Use ambient capabilities (`^`)**
- The `^` prefix ensures capabilities survive exec() - The `^` prefix ensures capabilities survive exec()
@@ -163,17 +173,17 @@ ps -o user,pid,cmd -p $(pidof nginx)
## Limitations ## Limitations
- The `caps:` directive requires `@user` to be specified for it to take effect - `capabilities` requires `user` to be set for it to take effect
- Without `@user`, the service runs as root with full capabilities and - Without `user`, the service runs as root with full capabilities and
the `caps:` configuration is silently ignored the `capabilities` list is silently ignored
- You can use `@root` with `caps:`, but see below about ambient capabilities - You can use `user = "root"`, but see below about ambient capabilities
- For ambient capabilities (`^`, recommended), the user **must be non-root** - For ambient capabilities (`^`, recommended), the user **must be non-root**
- Using `@root` with `caps:^...` will not work effectively, as ambient - Using `user = "root"` with `^` capabilities will not work effectively, as ambient
capabilities are only added to the effective set when euid ≠ 0 capabilities are only added to the effective set when euid ≠ 0
- Use inheritable (`%`) or bounding (`!`) capabilities with `@root` if needed - Use inheritable (`%`) or bounding (`!`) capabilities with `user = "root"` if needed
- Services without `caps:` use standard privilege dropping: - Services without `capabilities` use standard privilege dropping:
- Services with `@user` (non-root) have no special capabilities - Services with a non-root `user` have no special capabilities
- Services without `@user` run as root with full capabilities - Services without `user` run as root with full capabilities
- Some very old binaries may not work correctly with ambient capabilities - Some very old binaries may not work correctly with ambient capabilities
- File system capabilities are not managed by Finit (use `setcap` for that) - File system capabilities are not managed by Finit (use `setcap` for that)
+3 -3
View File
@@ -180,7 +180,7 @@ document [Finit Services](../service.md).
Alternate finit.d/ Alternate finit.d/
------------------ ------------------
**Syntax:** `rcsd /path/to/finit.d` **Syntax:** `rcsd = "/path/to/finit.d"`
The Finit rcS.d directory is set at compile time with: The Finit rcS.d directory is set at compile time with:
@@ -194,7 +194,7 @@ configurations, starting with the kernel command line option:
This file in turn can use the `rcsd` directive to tell Finit to use This file in turn can use the `rcsd` directive to tell Finit to use
another set of .conf files, e.g.: another set of .conf files, e.g.:
rcsd /etc/factory.d rcsd = "/etc/factory.d"
> [!NOTE] > [!NOTE]
> This directive is only available from the top-level bootstrap .conf > This directive is only available from the top-level bootstrap .conf
@@ -203,6 +203,6 @@ another set of .conf files, e.g.:
Including Finit Configs Including Finit Configs
------------------------ ------------------------
**Syntax:** `include <CONF>` **Syntax:** `include("CONF")`
Include another configuration file. Absolute path required. Include another configuration file. Absolute path required.
+2 -2
View File
@@ -1,13 +1,13 @@
General Logging General Logging
=============== ===============
**Syntax:** `log size:200k count:5` **Syntax:** `log { size = 200k count = 5 }`
Log rotation for run/task/services using the `log` sub-option with Log rotation for run/task/services using the `log` sub-option with
redirection to a log file. Global setting, applies to all services. redirection to a log file. Global setting, applies to all services.
The size can be given as bytes, without a specifier, or in `k`, `M`, The size can be given as bytes, without a specifier, or in `k`, `M`,
or `G`, e.g. `size:10M`, or `size:3G`. A value of `size:0` disables or `G`, e.g. `size = 10M`, or `size = 3G`. A value of `size = 0` disables
log rotation. The default is `200k`. log rotation. The default is `200k`.
The count value is recommended to be between 1-5, with a default 5. The count value is recommended to be between 1-5, with a default 5.
+21 -18
View File
@@ -66,7 +66,7 @@ least the loopback interface is brought up.
Runlevel Configuration Runlevel Configuration
---------------------- ----------------------
**Syntax:** `runlevel <N>` **Syntax:** `runlevel = N`
The system runlevel to go to after bootstrap (S) has completed. `N` is The system runlevel to go to after bootstrap (S) has completed. `N` is
the runlevel number 0-9, where 6 is reserved for reboot and 0 for halt. the runlevel number 0-9, where 6 is reserved for reboot and 0 for halt.
@@ -84,7 +84,7 @@ Finit disables networking in this mode.
Networking Networking
---------- ----------
**Syntax:** `network <PATH>` **Syntax:** `network = "PATH"`
Script or program to bring up networking, with optional arguments. Script or program to bring up networking, with optional arguments.
@@ -98,7 +98,7 @@ Debian, Ubuntu, Linux Mint, or an embedded BusyBox system.
System Hostname System Hostname
--------------- ---------------
**Syntax:** `host <NAME>`, or `hostname <NAME>` **Syntax:** `hostname = "NAME"`
Set system hostname to NAME, unless `/etc/hostname` exists in which case Set system hostname to NAME, unless `/etc/hostname` exists in which case
the contents of that file is used. the contents of that file is used.
@@ -111,10 +111,16 @@ Deprecated. We recommend using `/etc/hostname` instead.
Kernel Modules Kernel Modules
-------------- --------------
**Syntax:** `module <MODULE> [ARGS]` **Syntax:** `modules = { "MODULE [ARGS]", ... }`, alias `mod`
Load a kernel module, with optional arguments. Similar to `insmod` Load kernel modules, each with optional arguments. Similar to the
command line tool. `insmod` command line tool.
modules = { "button", "evdev", "softdog" }
> [!NOTE]
> A list cannot hold comments; the lexer reads the entries after a `#`
> regardless. Put commented-out candidates above the list.
Deprecated, there is both a `modules-load.so` and a `modprobe.so` plugin Deprecated, there is both a `modules-load.so` and a `modprobe.so` plugin
that can handle module loading better. The former supports loading from that can handle module loading better. The former supports loading from
@@ -130,9 +136,9 @@ BusyBox mdev tool, add to `/etc/mdev.conf`:
Resource Limits Resource Limits
--------------- ---------------
**Syntax:** `rlimit [hard|soft] RESOURCE <LIMIT|unlimited>` **Syntax:** `rlimit { RESOURCE = LIMIT }`, with `soft.` or `hard.` prefix
Set the hard or soft limit for a resource, or both if that argument is Set the hard or soft limit for a resource, or both if the prefix is
omitted. `RESOURCE` is the lower-case `RLIMIT_` string constants from omitted. `RESOURCE` is the lower-case `RLIMIT_` string constants from
`setrlimit(2)`, without prefix. E.g. to set `RLIMIT_CPU`, use `cpu`. `setrlimit(2)`, without prefix. E.g. to set `RLIMIT_CPU`, use `cpu`.
@@ -142,14 +148,11 @@ or the kernel `/proc/PID/limits` file, for details. Finit versions
before v3.1 used `infinity` for `unlimited`, which is still supported, before v3.1 used `infinity` for `unlimited`, which is still supported,
albeit deprecated. albeit deprecated.
# No process is allowed more than 8MB of address space rlimit {
rlimit hard as 8388608 hard.as = 8388608 # no more than 8MB of address space
soft.core = unlimited # core dumps may be arbitrarily large
# Core dumps may be arbitrarily large cpu = 10 # soft & hard = 10 sec
rlimit soft core infinity }
# CPU limit for all services, soft & hard = 10 sec
rlimit cpu 10
`rlimit` can be set globally, in `/etc/finit.conf`, or locally per `rlimit` can be set globally, in `/etc/finit.conf`, or locally per
each `/etc/finit.d/*.conf` read. I.e., a set of task/run/service each `/etc/finit.d/*.conf` read. I.e., a set of task/run/service
@@ -158,7 +161,7 @@ stanzas can share the same rlimits if they are in the same .conf.
Miscellaneous Settings Miscellaneous Settings
---------------------- ----------------------
**Syntax:** `reboot-delay <0-60>` **Syntax:** `reboot-delay = 0-60`
Optional delay at reboot (or shutdown or halt) to allow kernel Optional delay at reboot (or shutdown or halt) to allow kernel
filesystem threads to complete after calling `sync(2)` before filesystem threads to complete after calling `sync(2)` before
@@ -176,7 +179,7 @@ sync(2) has been called, twice.
> writing; it can actually take a short time before all the blocks are > writing; it can actually take a short time before all the blocks are
> finally written. > finally written.
**Syntax:** `reboot-watchdog <on|off|true|false|1|0>` **Syntax:** `reboot-watchdog = true|false`
Controls whether the system should reboot via the watchdog timer (WDT) Controls whether the system should reboot via the watchdog timer (WDT)
or directly via the SoC/kernel. When enabled, Finit will: or directly via the SoC/kernel. When enabled, Finit will:
+5 -4
View File
@@ -1,7 +1,7 @@
Run-parts Scripts Run-parts Scripts
----------------- -----------------
**Syntax:** `runparts [progress] [sysv] <DIR>` **Syntax:** `runparts = "DIR"`
Call [run-parts(8)][] on `DIR` to run start scripts. All executable Call [run-parts(8)][] on `DIR` to run start scripts. All executable
files in the directory are called, in alphabetic order. The scripts in files in the directory are called, in alphabetic order. The scripts in
@@ -14,9 +14,10 @@ whatever the next runlevel is set to be (default 2). E.g., generate a
**Options:** **Options:**
- `progress`: display the progress of each script being executed - `runparts-progress = true`: display the progress of each script being
- `sysv`: run only SysV style scripts, i.e., `SNNfoo`, or `KNNbar`, executed
where `NN` is a number (0-99). - `runparts-sysv = true`: run only SysV style scripts, i.e., `SNNfoo`,
or `KNNbar`, where `NN` is a number (0-99).
If global debug mode is enabled, the `runparts` program is also called If global debug mode is enabled, the `runparts` program is also called
with the debug flag. with the debug flag.
+2 -2
View File
@@ -43,8 +43,8 @@ like this:
service bar { notify = "s6" command = "bar" } service bar { notify = "s6" command = "bar" }
service qux { notify = "none" command = "qux" } service qux { notify = "none" command = "qux" }
The `notify:none` syntax is for completeness in systems which run in The `notify = "none"` setting is for completeness in systems which run in
`readiness pid` mode (default). Services declared with `notify:none` `readiness pid` mode (default). Services declared with `notify = "none"`
will transition to ready as soon as Finit has started them, e.g., will transition to ready as soon as Finit has started them, e.g.,
`service/qux/ready`. `service/qux/ready`.
+1 -1
View File
@@ -1,7 +1,7 @@
Services Services
======== ========
**Syntax:** `service [LVLS] <COND> /path/to/daemon ARGS -- Optional description` **Syntax:** `service NAME { command = "/path/to/daemon ARGS" }`
Service, or daemon, to be monitored and automatically restarted if it Service, or daemon, to be monitored and automatically restarted if it
exits prematurely. Finit tries to restart services that die, by default exits prematurely. Finit tries to restart services that die, by default
+2 -2
View File
@@ -9,7 +9,7 @@ from a serialized boot process.
SysV Init Scripts SysV Init Scripts
----------------- -----------------
**Syntax:** `sysv [LVLS] <COND> /path/to/init-script -- Optional description` **Syntax:** `sysv NAME { command = "/path/to/init-script" }`
> `<COND>` is described in the [Services](services.md) section. > `<COND>` is described in the [Services](services.md) section.
@@ -45,7 +45,7 @@ making it perfect for most scenarios.
For syntax details, see the [Run-parts Scripts](runparts.md) section. For syntax details, see the [Run-parts Scripts](runparts.md) section.
Here is an example take from a Debian installation: Here is an example take from a Debian installation:
runparts /etc/rc2.d runparts = "/etc/rc2.d"
Files in these directories are usually named `SNNfoo` and `KNNfoo`, Files in these directories are usually named `SNNfoo` and `KNNfoo`,
which Finit knows about and automatically appends the correct argument: which Finit knows about and automatically appends the correct argument:
+6 -6
View File
@@ -1,7 +1,7 @@
run (sequence) run (sequence)
-------------- --------------
**Syntax:** `run [LVLS] <COND> /path/to/cmd ARGS -- Optional description` **Syntax:** `run NAME { command = "/path/to/cmd ARGS" }`
> `<COND>` is described in the [Services](services.md) section. > `<COND>` is described in the [Services](services.md) section.
@@ -31,7 +31,7 @@ also the `--quiet` and `--batch` options.
task (parallel) task (parallel)
--------------- ---------------
**Syntax:** `task [LVLS] <COND> /path/to/cmd ARGS -- Optional description` **Syntax:** `task NAME { command = "/path/to/cmd ARGS" }`
> `<COND>` is described in the [Services](services.md) section. > `<COND>` is described in the [Services](services.md) section.
@@ -93,7 +93,7 @@ The firewall rules are created once. The `exec-stop-post` script runs when
entering runlevel 0 (halt) or 6 (reboot), or on explicit stop. entering runlevel 0 (halt) or 6 (reboot), or on explicit stop.
> [!NOTE] > [!NOTE]
> The `remain:yes` option is not supported for bootstrap-only tasks > The `remain-after-exit` option is not supported for bootstrap-only
> (tasks with only runlevel S). Bootstrap tasks are deleted immediately > tasks (tasks with only runlevel S). Bootstrap tasks are deleted
> after completion, and their `post:` scripts never run. A warning is > immediately after completion, and their `exec-stop-post` scripts never
> logged if `remain:yes` is used on such tasks. > run. A warning is logged if `remain-after-exit` is used on such tasks.
+24 -8
View File
@@ -1,16 +1,32 @@
TTYs and Consoles TTYs and Consoles
================= =================
**Syntax:** `tty [LVLS] <COND> DEV [BAUD] [noclear] [nowait] [nologin] [TERM]` **Syntax:** `tty NAME { device = DEV }` -- built-in getty
`tty [LVLS] <COND> CMD <ARGS> [noclear] [nowait]` `tty NAME { command = "CMD ARGS" }` -- external getty
`tty [LVLS] <COND> [notty] [rescue]` `tty NAME { notty = true }`, or `{ rescue = true }` -- bare shell, no device
The first variant of this option uses the built-in getty on the given The block title NAME is what `initctl` shows. The three variants differ
TTY device DEV, in the given runlevels. DEV may be the special keyword in what they open: `device` runs the built-in getty on that TTY, and DEV
`@console`, which is expanded from `/sys/class/tty/console/active`, may be the special keyword `@console`, expanded from
useful on embedded systems. `/sys/class/tty/console/active`, useful on embedded systems. `command`
hands the TTY to an external getty. `notty` opens nothing at all.
The default baud rate is 0, i.e., keep kernel default. Settings common to all three:
| Setting | Alias | Description |
|---|---|---|
| `runlevel` | | Runlevels to run in, e.g. `"12345"` |
| `conditions` | `cond` | Conditions to wait for |
| `noclear` | | Do not clear the TTY after each session |
| `nowait` | | Do not wait for Enter before the login prompt |
| `nologin` | | Skip login, give a shell straight away |
The `device` variant takes two more:
| Setting | Description |
|---|---|
| `baud` | Baud rate, default 0, i.e., keep kernel default |
| `term` | `$TERM` value, e.g. `"vt220"` |
> The `tty` stanza inherits runlevel, condition (and other feature) > The `tty` stanza inherits runlevel, condition (and other feature)
> parsing from the `service` stanza. So TTYs can run in one or many > parsing from the `service` stanza. So TTYs can run in one or many
+103 -49
View File
@@ -10,69 +10,126 @@ See the [contrib/][contrib] directory on GitHub for examples, or take a
peek at systems using Finit, like [Infix OS][infix] and [myLinux][]. peek at systems using Finit, like [Infix OS][infix] and [myLinux][].
> [!TIP] > [!TIP]
> As of Finit v4.4, `.conf` lines can be broken up using the standard UNIX > A block spans as many lines as it needs, so no continuation character is
> continuation character (`\`), trailing comments are also supported. The > called for. For the full syntax, see the [finit.conf(5)][] manual or the
> latter means you must escape any hashes used in directives and descriptions > [Configuration](config/index.md) section.
> (`\#`). For more on this and examples, see the [finit.conf(5)][] manual or
> the [Configuration](config/index.md) section.
```ApacheConf ```ApacheConf
# Fallback if /etc/hostname is missing # Fallback if /etc/hostname is missing
host default hostname = "default"
# Runlevel to start after bootstrap, 'S', default: 2 # Runlevel to start after bootstrap, 'S', default: 2
#runlevel 2 #runlevel = 2
# Support for setting global environment variables, using foo=bar syntax # Global environment variables, be careful though with variables like
# be careful though with variables like PATH, SHELL, LOGNAME, etc. # PATH, SHELL, LOGNAME, etc.
#PATH=/usr/bin:/bin:/usr/sbin:/sbin #environment {
# PATH = "/usr/bin:/bin:/usr/sbin:/sbin"
#}
# Max file size for each log file: 100 kiB, rotate max 4 copies: # Max file size for each log file: 100 kiB, rotate max 4 copies:
# log => log.1 => log.2.gz => log.3.gz => log.4.gz # log => log.1 => log.2.gz => log.3.gz => log.4.gz
log size=100k count=4 log {
size = 100k
count = 4
}
# Services to be monitored and respawned as needed # Services to be monitored and respawned as needed
service [S12345] env:-/etc/conf.d/watchdog watchdog $WATCHDOG_OPTS $WATCHDOG_DEV -- System watchdog daemon service watchdog {
service [S12345] env:-/etc/conf.d/syslog syslogd -n $SYSLOGD_OPTS -- System log daemon description = "System watchdog daemon"
service [S12345] <pid/syslogd> env:-/etc/conf.d/klogd klogd -n $KLOGD_OPTS -- Kernel log daemon runlevel = "S12345"
service [2345] env:-/etc/conf.d/lldpd lldpd -d $LLDPD_OPTS -- LLDP daemon (IEEE 802.1ab) envfile = "-/etc/conf.d/watchdog"
command = "watchdog $WATCHDOG_OPTS $WATCHDOG_DEV"
}
service syslogd {
description = "System log daemon"
runlevel = "S12345"
envfile = "-/etc/conf.d/syslog"
command = "syslogd -n $SYSLOGD_OPTS"
}
service klogd {
description = "Kernel log daemon"
runlevel = "S12345"
conditions = { "pid/syslogd" }
envfile = "-/etc/conf.d/klogd"
command = "klogd -n $KLOGD_OPTS"
}
service lldpd {
description = "LLDP daemon (IEEE 802.1ab)"
runlevel = "2345"
envfile = "-/etc/conf.d/lldpd"
command = "lldpd -d $LLDPD_OPTS"
}
# The BusyBox ntpd does not use syslog when running in the foreground # The BusyBox ntpd does not use syslog when running in the foreground
# So we use this trick to redirect stdout/stderr to a log file. The # So we use this trick to redirect stdout/stderr to a log file. The
# log file is rotated with the above settings. The condition declares # log file is rotated with the above settings. The condition declares
# a dependency on a system default route (gateway) to be set. A single # a dependency on a system default route (gateway) to be set. ntpd
# <!> at the beginning means ntpd does not respect SIGHUP for restart. # does not respect SIGHUP, so Finit restarts it on reload instead.
service [2345] log:/var/log/ntpd.log <!net/route/default> ntpd -n -l -I eth0 -- NTP daemon service ntpd {
description = "NTP daemon"
runlevel = "2345"
conditions = { "net/route/default" }
reload-signal = "none"
log { file = "/var/log/ntpd.log" }
command = "ntpd -n -l -I eth0"
}
# For multiple instances of the same service, add :ID somewhere between # For multiple instances of the same service, add :ID to the block title.
# the service/run/task keyword and the command. service merecat:80 {
service :80 [2345] merecat -n -p 80 /var/www -- Web server description = "Web server"
service :8080 [2345] merecat -n -p 8080 /var/www -- Old web server runlevel = "2345"
command = "merecat -n -p 80 /var/www"
}
service merecat:8080 {
description = "Old web server"
runlevel = "2345"
command = "merecat -n -p 8080 /var/www"
}
# Alternative method instead of below runparts, can also use /etc/rc.local # Alternative method instead of below runparts, can also use /etc/rc.local
#sysv [S] /etc/init.d/keyboard-setup -- Setting up preliminary keymap #sysv keyboard-setup {
#sysv [S] /etc/init.d/acpid -- Starting ACPI Daemon # description = "Setting up preliminary keymap"
#task [S] /etc/init.d/kbd -- Preparing console # runlevel = "S"
# command = "/etc/init.d/keyboard-setup"
#}
# Hidden from boot progress, using empty `--` description # Hidden from boot progress, using an empty description
#sysv [S] /etc/init.d/keyboard-setup -- #sysv acpid {
#sysv [S] /etc/init.d/acpid -- # description = ""
#task [S] /etc/init.d/kbd -- # runlevel = "S"
# command = "/etc/init.d/acpid"
#}
# Run start scripts from this directory # Run start scripts from this directory
# runparts /etc/start.d #runparts = "/etc/start.d"
# Virtual consoles run BusyBox getty, keep kernel default speed # Virtual consoles run BusyBox getty, keep kernel default speed
tty [12345] /sbin/getty -L 0 /dev/tty1 linux nowait noclear tty tty1 {
tty [2345] /sbin/getty -L 0 /dev/tty2 linux nowait noclear runlevel = "12345"
tty [2345] /sbin/getty -L 0 /dev/tty3 linux nowait noclear command = "/sbin/getty -L 0 /dev/tty1 linux"
nowait = true
noclear = true
}
tty tty2 {
runlevel = "2345"
command = "/sbin/getty -L 0 /dev/tty2 linux"
nowait = true
noclear = true
}
tty tty3 {
runlevel = "2345"
command = "/sbin/getty -L 0 /dev/tty3 linux"
nowait = true
noclear = true
}
# Use built-in getty for serial port and USB serial # Use built-in getty for serial port and USB serial
#tty [12345] /dev/ttyAMA0 noclear nowait #tty ttyAMA0 { runlevel = "12345" device = "/dev/ttyAMA0" noclear = true nowait = true }
#tty [12345] /dev/ttyUSB0 noclear #tty ttyUSB0 { runlevel = "12345" device = "/dev/ttyUSB0" noclear = true }
# Just give me a shell, I need to debug this embedded system! # Just give me a shell, I need to debug this embedded system!
#tty [12345] console noclear nologin #tty console { runlevel = "12345" device = "@console" noclear = true nologin = true }
``` ```
The `service` stanza, as well as `task`, `run` and others are described in The `service` stanza, as well as `task`, `run` and others are described in
@@ -82,21 +139,18 @@ Here's a quick overview of some of the most common components needed to start
a UNIX daemon: a UNIX daemon:
``` ```
service [LVLS] <COND> log env:[-]/etc/default/daemon daemon ARGS -- Example daemon service NAME { <-- Supervised program (daemon)
^ ^ ^ ^ ^ ^ ^ ^ description = "Example daemon" <-- Optional description
| | | | | | | `---------- Optional description runlevel = "2345" <-- Optional runlevels
| | | | | | `------------------ Daemon arguments conditions = { "net/route/default" } <-- Optional conditions
| | | | | `------------------------- Path to daemon envfile = "-/etc/default/daemon" <-- Optional env. file
| | | | `---------------------------------------------------- Optional env. file log { } <-- Redirect output to log
| | | `-------------------------------------------------------- Redirect output to log command = "daemon ARGS" <-- Path to daemon, and its arguments
| | `--------------------------------------------------------------- Optional conditions }
| `---------------------------------------------------------------------- Optional Runlevels
`------------------------------------------------------------------------------ Supervised program (daemon)
``` ```
Some components are optional: runlevel(s), condition(s) and description, Only `command` is required, which makes simple cases short while leaving
making it easy to create simple start scripts and still possible for more room for more advanced uses:
advanced uses as well:
service sshd { service sshd {
command = "/usr/sbin/sshd -D" command = "/usr/sbin/sshd -D"
+24 -12
View File
@@ -18,9 +18,9 @@ waits for user input before handing over to `/bin/login`, which is
responsible for handling the actual authentication. responsible for handling the actual authentication.
```conf ```conf
tty [12345] /dev/tty1 nowait linux tty tty1 { runlevel = "12345" device = "/dev/tty1" term = "linux" nowait = true }
tty [12345] /dev/ttyAMA0 noclear vt100 tty ttyAMA0 { runlevel = "12345" device = "/dev/ttyAMA0" term = "vt100" noclear = true }
tty [12345] /sbin/getty -L /dev/ttyAMA0 vt100 tty getty { runlevel = "12345" command = "/sbin/getty -L /dev/ttyAMA0 vt100" }
``` ```
Users of embedded systems may want to enable automatic serial console Users of embedded systems may want to enable automatic serial console
@@ -29,7 +29,7 @@ system uses `ttyS0`, `ttyAMA0`, `ttyMXC0`, or anything else. Finit
figures it out by querying sysfs: `/sys/class/tty/console/active`. figures it out by querying sysfs: `/sys/class/tty/console/active`.
```conf ```conf
tty [12345] @console linux noclear tty console { runlevel = "12345" device = "@console" term = "linux" noclear = true }
``` ```
Notice the optional `noclear`, `nowait`, and `nologin` flags. The Notice the optional `noclear`, `nowait`, and `nologin` flags. The
@@ -86,8 +86,17 @@ the condition `<hw/model/foo>` when starting other scripts. Here is an
example: example:
``` ```
run [S] /path/to/ident -- run ident {
task [2] <hw/model/foo> /path/to/foo-init -- Initializing Foo board description = ""
runlevel = "S"
command = "/path/to/ident"
}
task foo-init {
description = "Initializing Foo board"
runlevel = "2"
conditions = { "hw/model/foo" }
command = "/path/to/foo-init"
}
``` ```
> [!TIP] > [!TIP]
@@ -141,17 +150,20 @@ required privileges instead of running as root. This improves security by
following the principle of least privilege. following the principle of least privilege.
```conf ```conf
service [2345] name:nginx \ service nginx {
www-data:www-data \ runlevel = "2345"
caps:^cap_net_bind_service \ user = "www-data"
/usr/sbin/nginx -g 'daemon off;' group = "www-data"
capabilities = { "^cap_net_bind_service" }
command = "/usr/sbin/nginx -g 'daemon off;'"
}
``` ```
In this example, nginx runs as the unprivileged `www-data` user but retains In this example, nginx runs as the unprivileged `www-data` user but retains
the ability to bind to privileged ports (80, 443) through the the ability to bind to privileged ports (80, 443) through the
`cap_net_bind_service` capability. `cap_net_bind_service` capability.
The `caps:` directive uses the IAB (Inheritable, Ambient, Bounding) format: The `capabilities` list uses the IAB (Inheritable, Ambient, Bounding) format:
- `^` = Ambient (recommended) - capabilities survive exec() - `^` = Ambient (recommended) - capabilities survive exec()
- `%` = Inheritable only - requires file capabilities - `%` = Inheritable only - requires file capabilities
- `!` = Bounding - block from acquiring capability - `!` = Bounding - block from acquiring capability
@@ -159,7 +171,7 @@ The `caps:` directive uses the IAB (Inheritable, Ambient, Bounding) format:
Multiple capabilities can be specified as comma-separated: Multiple capabilities can be specified as comma-separated:
```conf ```conf
caps:^cap_net_raw,^cap_net_admin,!cap_sys_admin capabilities = { "^cap_net_raw", "^cap_net_admin", "!cap_sys_admin" }
``` ```
See the [Linux Capabilities](config/capabilities.md) section for detailed See the [Linux Capabilities](config/capabilities.md) section for detailed
+1 -1
View File
@@ -71,7 +71,7 @@ For your convenience a set of *optional* plugins are available:
comment character, `#`, or `;`, is skipped. comment character, `#`, or `;`, is skipped.
Modules are by default loaded in runlevel `S` using the `task` stanza. Modules are by default loaded in runlevel `S` using the `task` stanza.
Each module gets a unique `name:modprobe.foo`, and optional`:ID`. The Each module is named `modprobe.foo`, with an optional `:ID`. The
runlevel can be changed per file using: runlevel can be changed per file using:
set runlevel 2345 set runlevel 2345
+5 -1
View File
@@ -15,7 +15,11 @@ done slightly differently and on systems with udev you might want to add
the following one-shot task early in your `/etc/finit.conf`: the following one-shot task early in your `/etc/finit.conf`:
```conf ```conf
run [S] udevadm settle --timeout=120 -- Waiting for udev run udevadm {
description = "Waiting for udev"
runlevel = "S"
command = "udevadm settle --timeout=120"
}
``` ```
Finit has a built-in Getty for TTYs, but requires a working `/bin/login` Finit has a built-in Getty for TTYs, but requires a working `/bin/login`
+36 -13
View File
@@ -13,20 +13,37 @@ more of a policy for the user to define. Normally only runlevels 1-6
are used, and even more commonly, only the default runlevel is used. are used, and even more commonly, only the default runlevel is used.
To specify an allowed set of runlevels for a `service`, `run` command, To specify an allowed set of runlevels for a `service`, `run` command,
`task`, or `tty`, add `[NNN]` to your `/etc/finit.conf`, like this: `task`, or `tty`, set `runlevel` in your `/etc/finit.conf`, like this:
``` ```
service [S12345] syslogd -n -x -- System log daemon service syslogd {
run [S] /etc/init.d/acpid start -- Starting ACPI Daemon description = "System log daemon"
task [S] /etc/init.d/kbd start -- Preparing console runlevel = "S12345"
service [S12345] <pid/syslogd> klogd -n -x -- Kernel log daemon command = "syslogd -n -x"
}
run acpid {
description = "Starting ACPI Daemon"
runlevel = "S"
command = "/etc/init.d/acpid start"
}
task kbd {
description = "Preparing console"
runlevel = "S"
command = "/etc/init.d/kbd start"
}
service klogd {
description = "Kernel log daemon"
runlevel = "S12345"
conditions = { "pid/syslogd" }
command = "klogd -n -x"
}
tty [12345] /dev/tty1 tty tty1 { runlevel = "12345" device = "/dev/tty1" }
tty [2] /dev/tty2 tty tty2 { runlevel = "2" device = "/dev/tty2" }
tty [2] /dev/tty3 tty tty3 { runlevel = "2" device = "/dev/tty3" }
tty [2] /dev/tty4 tty tty4 { runlevel = "2" device = "/dev/tty4" }
tty [2] /dev/tty5 tty tty5 { runlevel = "2" device = "/dev/tty5" }
tty [2] /dev/tty6 tty tty6 { runlevel = "2" device = "/dev/tty6" }
``` ```
In this example syslogd is first started, in parallel, and then acpid is In this example syslogd is first started, in parallel, and then acpid is
@@ -46,8 +63,14 @@ are also removed when they have completed, `initctl show` will not list
them. them.
``` ```
task [S] echo "foo" | cat >/tmp/bar task foo {
run [S] echo "$HOME" >/tmp/secret runlevel = "S"
command = "echo \"foo\" | cat >/tmp/bar"
}
run secret {
runlevel = "S"
command = "echo \"$HOME\" >/tmp/secret"
}
``` ```
Switching between runlevels can be done by calling init with a single Switching between runlevels can be done by calling init with a single
+55 -11
View File
@@ -51,27 +51,52 @@ Configuration file `/etc/finit.conf` in the initramfs:
# /etc/finit.conf in initramfs # /etc/finit.conf in initramfs
# Mount the real root filesystem # Mount the real root filesystem
run [S] name:mount-root /bin/mount /dev/sda1 /mnt/root -- Mounting root filesystem run mount-root {
description = "Mounting root filesystem"
runlevel = "S"
command = "/bin/mount /dev/sda1 /mnt/root"
}
# Switch to real root after mount completes # Switch to real root after mount completes
run [S] name:switch-root /sbin/initctl switch-root /mnt/root -- Switching to real root run switch-root {
description = "Switching to real root"
runlevel = "S"
command = "/sbin/initctl switch-root /mnt/root"
}
``` ```
For more complex setups (LUKS, LVM, etc.): For more complex setups (LUKS, LVM, etc.):
``` ```
# Unlock LUKS volume # Unlock LUKS volume
# The tty:@console stanza is required so cryptsetup can prompt for a passphrase # The tty setting is required so cryptsetup can prompt for a passphrase
run [S] name:cryptsetup tty:@console /sbin/cryptsetup open /dev/sda2 cryptroot -- Unlocking encrypted root run cryptsetup {
description = "Unlocking encrypted root"
runlevel = "S"
tty = "@console"
command = "/sbin/cryptsetup open /dev/sda2 cryptroot"
}
# Activate LVM # Activate LVM
run [S] name:lvm /sbin/lvm vgchange -ay -- Activating LVM volumes run lvm {
description = "Activating LVM volumes"
runlevel = "S"
command = "/sbin/lvm vgchange -ay"
}
# Mount root # Mount root
run [S] name:mount-root /bin/mount /dev/vg0/root /mnt/root -- Mounting root run mount-root {
description = "Mounting root"
runlevel = "S"
command = "/bin/mount /dev/vg0/root /mnt/root"
}
# Switch root # Switch root
run [S] name:switch-root /sbin/initctl switch-root /mnt/root -- Switching to real root run switch-root {
description = "Switching to real root"
runlevel = "S"
command = "/sbin/initctl switch-root /mnt/root"
}
``` ```
@@ -85,15 +110,34 @@ difficult in runlevel S, you can perform the switch-root in runlevel 1:
# /etc/finit.conf in initramfs # /etc/finit.conf in initramfs
# Start mdevd for device handling # Start mdevd for device handling
service [S] name:mdevd notify:s6 /sbin/mdevd -D %n -- Device event daemon service mdevd {
run [S] name:coldplug <service/mdevd/ready> /sbin/mdevd-coldplug -- Coldplug devices description = "Device event daemon"
runlevel = "S"
notify = "s6"
command = "/sbin/mdevd -D %n"
}
run coldplug {
description = "Coldplug devices"
runlevel = "S"
conditions = { "service/mdevd/ready" }
command = "/sbin/mdevd-coldplug"
}
# Mount the real root filesystem (after devices are ready) # Mount the real root filesystem (after devices are ready)
run [S] name:mount-root <run/coldplug/success> /bin/mount /dev/sda1 /mnt/root -- Mounting root run mount-root {
description = "Mounting root"
runlevel = "S"
conditions = { "run/coldplug/success" }
command = "/bin/mount /dev/sda1 /mnt/root"
}
# Transition to runlevel 1 after all S tasks complete # Transition to runlevel 1 after all S tasks complete
# The switch-root runs cleanly in runlevel 1 # The switch-root runs cleanly in runlevel 1
run [1] name:switch-root /sbin/initctl switch-root /mnt/root -- Switching to real root run switch-root {
description = "Switching to real root"
runlevel = "1"
command = "/sbin/initctl switch-root /mnt/root"
}
``` ```
This approach separates the initramfs setup (runlevel S) from the This approach separates the initramfs setup (runlevel S) from the