diff --git a/doc/conditions.md b/doc/conditions.md index 036278d6..d16ebaa3 100644 --- a/doc/conditions.md +++ b/doc/conditions.md @@ -242,16 +242,16 @@ Composition ----------- 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 -the daemon and the empty string. +composed from a service's block title and its `:id`. By default the +basename of the daemon and the empty string. -| **service** | **condition** | -|----------------------------------------------------|------------------| -| /sbin/foo | pid/foo | -| /sbin/bar -p /run/baz.pid | pid/bar | -| name:lxc :foo lxc-start -n foo -p /run/lxc/foo.pid | pid/lxc:foo | -| /usr/bin/dbus-daemon | pid/dbus-daemon | -| :222 dropbear -p 222 | pid/dropbear:222 | +| **service** | **condition** | +|-------------------------------------------------------------------|------------------| +| `service { command = "/sbin/foo" }` | pid/foo | +| `service { command = "/sbin/bar -p /run/baz.pid" }` | pid/bar | +| `service lxc:foo { command = "lxc-start -n foo -p /run/lxc/foo.pid" }` | pid/lxc:foo | +| `service { command = "/usr/bin/dbus-daemon" }` | pid/dbus-daemon | +| `service dropbear:222 { command = "dropbear -p 222" }` | pid/dropbear:222 | The condition is asserted when `pidfile.so` receives an inotify event for a file matching `/run/*.pid`, `/run/**/*.pid`, or `/run/**/pid`, diff --git a/doc/config/capabilities.md b/doc/config/capabilities.md index 8c89d392..5aa16c0a 100644 --- a/doc/config/capabilities.md +++ b/doc/config/capabilities.md @@ -16,14 +16,17 @@ which is the same approach used by other modern service managers like dinit. ## Basic Usage -Capabilities are specified using the `caps:` directive in service configuration: +Capabilities are specified with the `capabilities` key, alias `caps`: ```conf -service [2345] name:nginx \ - @www-data:www-data \ - caps:^cap_net_bind_service \ - /usr/sbin/nginx -g 'daemon off;' \ - -- Web server +service nginx { + description = "Web server" + runlevel = "2345" + user = "www-data" + 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 @@ -52,7 +55,7 @@ with the following prefixes: Multiple capabilities can be specified as a comma-separated list: ```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 @@ -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: ```conf -service [2345] name:webserver \ - @www-data:www-data \ - caps:^cap_net_bind_service \ - /usr/sbin/nginx -g 'daemon off;' +service webserver { + runlevel = "2345" + user = "www-data" + group = "www-data" + capabilities = { "^cap_net_bind_service" } + command = "/usr/sbin/nginx -g 'daemon off;'" +} ``` ### Network Monitoring (Raw Sockets) @@ -73,10 +79,12 @@ service [2345] name:webserver \ Allow packet capture without root privileges: ```conf -service [2345] name:tcpdump \ - @tcpdump \ - caps:^cap_net_raw,^cap_net_admin \ - /usr/sbin/tcpdump -i eth0 -w /var/log/capture.pcap +service tcpdump { + runlevel = "2345" + user = "tcpdump" + capabilities = { "^cap_net_raw", "^cap_net_admin" } + command = "/usr/sbin/tcpdump -i eth0 -w /var/log/capture.pcap" +} ``` ### NTP Daemon (System Time) @@ -84,10 +92,12 @@ service [2345] name:tcpdump \ Allow time synchronization without full root: ```conf -service [2345] name:ntpd \ - @ntp \ - caps:^cap_sys_time,^cap_sys_nice \ - /usr/sbin/ntpd -n +service ntpd { + runlevel = "2345" + user = "ntp" + capabilities = { "^cap_sys_time", "^cap_sys_nice" } + command = "/usr/sbin/ntpd -n" +} ``` ## 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 2. **Specify a user (preferably non-root)** - - The `@user` directive is **required** for `caps:` to take effect - - For ambient capabilities (`^`), use a non-root user (not `@root`) - - Example: `@www-data`, `@nginx`, `@tcpdump` + - The `user` setting is **required** for `capabilities` to take effect + - For ambient capabilities (`^`), use a non-root user (not `"root"`) + - Example: `user = "www-data"`, `user = "nginx"`, `user = "tcpdump"` 3. **Use ambient capabilities (`^`)** - The `^` prefix ensures capabilities survive exec() @@ -163,17 +173,17 @@ ps -o user,pid,cmd -p $(pidof nginx) ## Limitations -- The `caps:` directive requires `@user` to be specified for it to take effect - - Without `@user`, the service runs as root with full capabilities and - the `caps:` configuration is silently ignored - - You can use `@root` with `caps:`, but see below about ambient capabilities +- `capabilities` requires `user` to be set for it to take effect + - Without `user`, the service runs as root with full capabilities and + the `capabilities` list is silently ignored + - You can use `user = "root"`, but see below about ambient capabilities - 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 - - Use inheritable (`%`) or bounding (`!`) capabilities with `@root` if needed -- Services without `caps:` use standard privilege dropping: - - Services with `@user` (non-root) have no special capabilities - - Services without `@user` run as root with full capabilities + - Use inheritable (`%`) or bounding (`!`) capabilities with `user = "root"` if needed +- Services without `capabilities` use standard privilege dropping: + - Services with a non-root `user` have no special capabilities + - Services without `user` run as root with full capabilities - Some very old binaries may not work correctly with ambient capabilities - File system capabilities are not managed by Finit (use `setcap` for that) diff --git a/doc/config/files.md b/doc/config/files.md index bc004e52..9e084d5c 100644 --- a/doc/config/files.md +++ b/doc/config/files.md @@ -180,7 +180,7 @@ document [Finit Services](../service.md). 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: @@ -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 another set of .conf files, e.g.: - rcsd /etc/factory.d + rcsd = "/etc/factory.d" > [!NOTE] > 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 ------------------------ -**Syntax:** `include ` +**Syntax:** `include("CONF")` Include another configuration file. Absolute path required. diff --git a/doc/config/logging.md b/doc/config/logging.md index 57427412..743fd34d 100644 --- a/doc/config/logging.md +++ b/doc/config/logging.md @@ -1,13 +1,13 @@ 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 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`, -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`. The count value is recommended to be between 1-5, with a default 5. diff --git a/doc/config/runlevels.md b/doc/config/runlevels.md index 16f95085..bb7d97cd 100644 --- a/doc/config/runlevels.md +++ b/doc/config/runlevels.md @@ -66,7 +66,7 @@ least the loopback interface is brought up. Runlevel Configuration ---------------------- -**Syntax:** `runlevel ` +**Syntax:** `runlevel = N` 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. @@ -84,7 +84,7 @@ Finit disables networking in this mode. Networking ---------- -**Syntax:** `network ` +**Syntax:** `network = "PATH"` 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 --------------- -**Syntax:** `host `, or `hostname ` +**Syntax:** `hostname = "NAME"` Set system hostname to NAME, unless `/etc/hostname` exists in which case the contents of that file is used. @@ -111,10 +111,16 @@ Deprecated. We recommend using `/etc/hostname` instead. Kernel Modules -------------- -**Syntax:** `module [ARGS]` +**Syntax:** `modules = { "MODULE [ARGS]", ... }`, alias `mod` -Load a kernel module, with optional arguments. Similar to `insmod` -command line tool. +Load kernel modules, each with optional arguments. Similar to the +`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 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 --------------- -**Syntax:** `rlimit [hard|soft] RESOURCE ` +**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 `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, albeit deprecated. - # No process is allowed more than 8MB of address space - rlimit hard as 8388608 - - # Core dumps may be arbitrarily large - rlimit soft core infinity - - # CPU limit for all services, soft & hard = 10 sec - rlimit cpu 10 + rlimit { + hard.as = 8388608 # no more than 8MB of address space + soft.core = unlimited # core dumps may be arbitrarily large + cpu = 10 # soft & hard = 10 sec + } `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 @@ -158,7 +161,7 @@ stanzas can share the same rlimits if they are in the same .conf. Miscellaneous Settings ---------------------- -**Syntax:** `reboot-delay <0-60>` +**Syntax:** `reboot-delay = 0-60` Optional delay at reboot (or shutdown or halt) to allow kernel 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 > finally written. -**Syntax:** `reboot-watchdog ` +**Syntax:** `reboot-watchdog = true|false` Controls whether the system should reboot via the watchdog timer (WDT) or directly via the SoC/kernel. When enabled, Finit will: diff --git a/doc/config/runparts.md b/doc/config/runparts.md index 0a074449..ba97a569 100644 --- a/doc/config/runparts.md +++ b/doc/config/runparts.md @@ -1,7 +1,7 @@ Run-parts Scripts ----------------- -**Syntax:** `runparts [progress] [sysv] ` +**Syntax:** `runparts = "DIR"` Call [run-parts(8)][] on `DIR` to run start scripts. All executable 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:** - - `progress`: display the progress of each script being executed - - `sysv`: run only SysV style scripts, i.e., `SNNfoo`, or `KNNbar`, - where `NN` is a number (0-99). + - `runparts-progress = true`: display the progress of each script being + executed + - `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 with the debug flag. diff --git a/doc/config/service-sync.md b/doc/config/service-sync.md index 46aabd15..1cf05319 100644 --- a/doc/config/service-sync.md +++ b/doc/config/service-sync.md @@ -43,8 +43,8 @@ like this: service bar { notify = "s6" command = "bar" } service qux { notify = "none" command = "qux" } -The `notify:none` syntax is for completeness in systems which run in -`readiness pid` mode (default). Services declared with `notify:none` +The `notify = "none"` setting is for completeness in systems which run in +`readiness pid` mode (default). Services declared with `notify = "none"` will transition to ready as soon as Finit has started them, e.g., `service/qux/ready`. diff --git a/doc/config/services.md b/doc/config/services.md index 7dbe49b7..8070acbd 100644 --- a/doc/config/services.md +++ b/doc/config/services.md @@ -1,7 +1,7 @@ Services ======== -**Syntax:** `service [LVLS] /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 exits prematurely. Finit tries to restart services that die, by default diff --git a/doc/config/sysv.md b/doc/config/sysv.md index e9378bfb..2a59a7c8 100644 --- a/doc/config/sysv.md +++ b/doc/config/sysv.md @@ -9,7 +9,7 @@ from a serialized boot process. SysV Init Scripts ----------------- -**Syntax:** `sysv [LVLS] /path/to/init-script -- Optional description` +**Syntax:** `sysv NAME { command = "/path/to/init-script" }` > `` 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. 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`, which Finit knows about and automatically appends the correct argument: diff --git a/doc/config/task-and-run.md b/doc/config/task-and-run.md index 9f4994c6..17f9c7f7 100644 --- a/doc/config/task-and-run.md +++ b/doc/config/task-and-run.md @@ -1,7 +1,7 @@ run (sequence) -------------- -**Syntax:** `run [LVLS] /path/to/cmd ARGS -- Optional description` +**Syntax:** `run NAME { command = "/path/to/cmd ARGS" }` > `` is described in the [Services](services.md) section. @@ -31,7 +31,7 @@ also the `--quiet` and `--batch` options. task (parallel) --------------- -**Syntax:** `task [LVLS] /path/to/cmd ARGS -- Optional description` +**Syntax:** `task NAME { command = "/path/to/cmd ARGS" }` > `` 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. > [!NOTE] -> The `remain:yes` option is not supported for bootstrap-only tasks -> (tasks with only runlevel S). Bootstrap tasks are deleted immediately -> after completion, and their `post:` scripts never run. A warning is -> logged if `remain:yes` is used on such tasks. +> The `remain-after-exit` option is not supported for bootstrap-only +> tasks (tasks with only runlevel S). Bootstrap tasks are deleted +> immediately after completion, and their `exec-stop-post` scripts never +> run. A warning is logged if `remain-after-exit` is used on such tasks. diff --git a/doc/config/tty.md b/doc/config/tty.md index fd0ee76a..616e504b 100644 --- a/doc/config/tty.md +++ b/doc/config/tty.md @@ -1,16 +1,32 @@ TTYs and Consoles ================= -**Syntax:** `tty [LVLS] DEV [BAUD] [noclear] [nowait] [nologin] [TERM]` - `tty [LVLS] CMD [noclear] [nowait]` - `tty [LVLS] [notty] [rescue]` +**Syntax:** `tty NAME { device = DEV }` -- built-in getty + `tty NAME { command = "CMD ARGS" }` -- external getty + `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 -TTY device DEV, in the given runlevels. DEV may be the special keyword -`@console`, which is expanded from `/sys/class/tty/console/active`, -useful on embedded systems. +The block title NAME is what `initctl` shows. The three variants differ +in what they open: `device` runs the built-in getty on that TTY, and DEV +may be the special keyword `@console`, expanded from +`/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) > parsing from the `service` stanza. So TTYs can run in one or many diff --git a/doc/example.md b/doc/example.md index 527961e5..cd47fdb1 100644 --- a/doc/example.md +++ b/doc/example.md @@ -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][]. > [!TIP] -> As of Finit v4.4, `.conf` lines can be broken up using the standard UNIX -> continuation character (`\`), trailing comments are also supported. The -> latter means you must escape any hashes used in directives and descriptions -> (`\#`). For more on this and examples, see the [finit.conf(5)][] manual or -> the [Configuration](config/index.md) section. +> A block spans as many lines as it needs, so no continuation character is +> called for. For the full syntax, see the [finit.conf(5)][] manual or the +> [Configuration](config/index.md) section. ```ApacheConf # Fallback if /etc/hostname is missing -host default +hostname = "default" # Runlevel to start after bootstrap, 'S', default: 2 -#runlevel 2 +#runlevel = 2 -# Support for setting global environment variables, using foo=bar syntax -# be careful though with variables like PATH, SHELL, LOGNAME, etc. -#PATH=/usr/bin:/bin:/usr/sbin:/sbin +# Global environment variables, be careful though with variables like +# PATH, SHELL, LOGNAME, etc. +#environment { +# PATH = "/usr/bin:/bin:/usr/sbin:/sbin" +#} # 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 size=100k count=4 +log { + size = 100k + count = 4 +} # Services to be monitored and respawned as needed -service [S12345] env:-/etc/conf.d/watchdog watchdog $WATCHDOG_OPTS $WATCHDOG_DEV -- System watchdog daemon -service [S12345] env:-/etc/conf.d/syslog syslogd -n $SYSLOGD_OPTS -- System log daemon -service [S12345] env:-/etc/conf.d/klogd klogd -n $KLOGD_OPTS -- Kernel log daemon -service [2345] env:-/etc/conf.d/lldpd lldpd -d $LLDPD_OPTS -- LLDP daemon (IEEE 802.1ab) +service watchdog { + description = "System watchdog daemon" + runlevel = "S12345" + 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 # 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 -# a dependency on a system default route (gateway) to be set. A single -# at the beginning means ntpd does not respect SIGHUP for restart. -service [2345] log:/var/log/ntpd.log ntpd -n -l -I eth0 -- NTP daemon +# a dependency on a system default route (gateway) to be set. ntpd +# does not respect SIGHUP, so Finit restarts it on reload instead. +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 -# the service/run/task keyword and the command. -service :80 [2345] merecat -n -p 80 /var/www -- Web server -service :8080 [2345] merecat -n -p 8080 /var/www -- Old web server +# For multiple instances of the same service, add :ID to the block title. +service merecat:80 { + description = "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 -#sysv [S] /etc/init.d/keyboard-setup -- Setting up preliminary keymap -#sysv [S] /etc/init.d/acpid -- Starting ACPI Daemon -#task [S] /etc/init.d/kbd -- Preparing console +#sysv keyboard-setup { +# description = "Setting up preliminary keymap" +# runlevel = "S" +# command = "/etc/init.d/keyboard-setup" +#} -# Hidden from boot progress, using empty `--` description -#sysv [S] /etc/init.d/keyboard-setup -- -#sysv [S] /etc/init.d/acpid -- -#task [S] /etc/init.d/kbd -- +# Hidden from boot progress, using an empty description +#sysv acpid { +# description = "" +# runlevel = "S" +# command = "/etc/init.d/acpid" +#} # Run start scripts from this directory -# runparts /etc/start.d +#runparts = "/etc/start.d" # Virtual consoles run BusyBox getty, keep kernel default speed -tty [12345] /sbin/getty -L 0 /dev/tty1 linux nowait noclear -tty [2345] /sbin/getty -L 0 /dev/tty2 linux nowait noclear -tty [2345] /sbin/getty -L 0 /dev/tty3 linux nowait noclear +tty tty1 { + runlevel = "12345" + 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 -#tty [12345] /dev/ttyAMA0 noclear nowait -#tty [12345] /dev/ttyUSB0 noclear +#tty ttyAMA0 { runlevel = "12345" device = "/dev/ttyAMA0" noclear = true nowait = true } +#tty ttyUSB0 { runlevel = "12345" device = "/dev/ttyUSB0" noclear = true } # 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 @@ -82,21 +139,18 @@ Here's a quick overview of some of the most common components needed to start a UNIX daemon: ``` -service [LVLS] log env:[-]/etc/default/daemon daemon ARGS -- Example daemon -^ ^ ^ ^ ^ ^ ^ ^ -| | | | | | | `---------- Optional description -| | | | | | `------------------ Daemon arguments -| | | | | `------------------------- Path to daemon -| | | | `---------------------------------------------------- Optional env. file -| | | `-------------------------------------------------------- Redirect output to log -| | `--------------------------------------------------------------- Optional conditions -| `---------------------------------------------------------------------- Optional Runlevels - `------------------------------------------------------------------------------ Supervised program (daemon) +service NAME { <-- Supervised program (daemon) + description = "Example daemon" <-- Optional description + runlevel = "2345" <-- Optional runlevels + conditions = { "net/route/default" } <-- Optional conditions + envfile = "-/etc/default/daemon" <-- Optional env. file + log { } <-- Redirect output to log + command = "daemon ARGS" <-- Path to daemon, and its arguments +} ``` -Some components are optional: runlevel(s), condition(s) and description, -making it easy to create simple start scripts and still possible for more -advanced uses as well: +Only `command` is required, which makes simple cases short while leaving +room for more advanced uses: service sshd { command = "/usr/sbin/sshd -D" diff --git a/doc/features.md b/doc/features.md index 5f604a77..564db42a 100644 --- a/doc/features.md +++ b/doc/features.md @@ -18,9 +18,9 @@ waits for user input before handing over to `/bin/login`, which is responsible for handling the actual authentication. ```conf -tty [12345] /dev/tty1 nowait linux -tty [12345] /dev/ttyAMA0 noclear vt100 -tty [12345] /sbin/getty -L /dev/ttyAMA0 vt100 +tty tty1 { runlevel = "12345" device = "/dev/tty1" term = "linux" nowait = true } +tty ttyAMA0 { runlevel = "12345" device = "/dev/ttyAMA0" term = "vt100" noclear = true } +tty getty { runlevel = "12345" command = "/sbin/getty -L /dev/ttyAMA0 vt100" } ``` 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`. ```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 @@ -86,8 +86,17 @@ the condition `` when starting other scripts. Here is an example: ``` -run [S] /path/to/ident -- -task [2] /path/to/foo-init -- Initializing Foo board +run ident { + 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] @@ -141,17 +150,20 @@ required privileges instead of running as root. This improves security by following the principle of least privilege. ```conf -service [2345] name:nginx \ - www-data:www-data \ - caps:^cap_net_bind_service \ - /usr/sbin/nginx -g 'daemon off;' +service nginx { + runlevel = "2345" + user = "www-data" + 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 the ability to bind to privileged ports (80, 443) through the `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() - `%` = Inheritable only - requires file capabilities - `!` = 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: ```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 diff --git a/doc/plugins.md b/doc/plugins.md index 73bdd9a3..5a889677 100644 --- a/doc/plugins.md +++ b/doc/plugins.md @@ -71,7 +71,7 @@ For your convenience a set of *optional* plugins are available: comment character, `#`, or `;`, is skipped. 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: set runlevel 2345 diff --git a/doc/requirements.md b/doc/requirements.md index 89e6f872..5b24f8a2 100644 --- a/doc/requirements.md +++ b/doc/requirements.md @@ -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`: ```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` diff --git a/doc/runlevels.md b/doc/runlevels.md index f03fecac..e976cf15 100644 --- a/doc/runlevels.md +++ b/doc/runlevels.md @@ -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. 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 -run [S] /etc/init.d/acpid start -- Starting ACPI Daemon -task [S] /etc/init.d/kbd start -- Preparing console -service [S12345] klogd -n -x -- Kernel log daemon +service syslogd { + description = "System log daemon" + runlevel = "S12345" + 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 [2] /dev/tty2 -tty [2] /dev/tty3 -tty [2] /dev/tty4 -tty [2] /dev/tty5 -tty [2] /dev/tty6 +tty tty1 { runlevel = "12345" device = "/dev/tty1" } +tty tty2 { runlevel = "2" device = "/dev/tty2" } +tty tty3 { runlevel = "2" device = "/dev/tty3" } +tty tty4 { runlevel = "2" device = "/dev/tty4" } +tty tty5 { runlevel = "2" device = "/dev/tty5" } +tty tty6 { runlevel = "2" device = "/dev/tty6" } ``` 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. ``` -task [S] echo "foo" | cat >/tmp/bar -run [S] echo "$HOME" >/tmp/secret +task foo { + 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 diff --git a/doc/switchroot.md b/doc/switchroot.md index c342b487..848c2e4c 100644 --- a/doc/switchroot.md +++ b/doc/switchroot.md @@ -51,27 +51,52 @@ Configuration file `/etc/finit.conf` in the initramfs: # /etc/finit.conf in initramfs # 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 -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.): ``` # Unlock LUKS volume -# The tty:@console stanza is required so cryptsetup can prompt for a passphrase -run [S] name:cryptsetup tty:@console /sbin/cryptsetup open /dev/sda2 cryptroot -- Unlocking encrypted root +# The tty setting is required so cryptsetup can prompt for a passphrase +run cryptsetup { + description = "Unlocking encrypted root" + runlevel = "S" + tty = "@console" + command = "/sbin/cryptsetup open /dev/sda2 cryptroot" +} # 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 -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 -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 # Start mdevd for device handling -service [S] name:mdevd notify:s6 /sbin/mdevd -D %n -- Device event daemon -run [S] name:coldplug /sbin/mdevd-coldplug -- Coldplug devices +service mdevd { + 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) -run [S] name:mount-root /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 # 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