Hello everyone!

I was working on alpine's /init script and started contemplating if/how it would look like if it was a set of obarun services. I thought this would be a fun experiment so I wanted to share my ideas. Currently, alpine's init script is the bane of my existence as it's a single shell script that's very hard to extend, and I thought that 66 could offer the possibility to split up everything.

It seems systemd always uses service template files for the initramfs init, so it's not that far off.

Firstly, I think the correct way to do this would be to create a module file which contains all the needed files for each specific service. The services can easily be well isolated: busybox-init, skeleton, keymap, networking, storage, etc..

Issues

Of course, the only interesting part is to think about the known issues that could be encountered.

1. Re-usable functions

Currently, afaik, I don't think there is a way to re-use many scripts in many obarun services, expect maybe putting all the needed scripts in a file and then manually loading that file in each service module that needs it. Examples of re-usable functions in alpine's init script are: ebegin, eend, rc_add, ``, etc..

OpenRC has /lib/rc/sh/functions.sh and /lib/rc/bin/* which is automatically added to any module's path I think

2. Shared environment

I'm not sure if this is possible that module service files can have a shared, but dynamic environment. For example, it would be nice that not each script needs to parse the kernel cmdline each time, and that task can be delegated to one service, which can then maybe update the whole environment of the whole module service.

Also useful in scenarios like this: add openssh to pkgs_to_install when the cmdline option ssh_key is detected.

That would be nice, atleast I think so.

3. Extensibility

Module services are currently too isolated, and this means that we can't easily do cool stuff like these (alpine's init script suffers the same too):

  1. add unlOkr or clevis to ease unlocking of LUKS partitions. All these services would need to do is say provides=( luks-decrypt ) (or requiredby in case they still want to use the normal method as fallback, assuming luks-decrypt would skip already decrypted-devices.
  2. add boot speed measuring using stuff like bootchart
  3. Show a custom bootsplash using pbsplash
  4. etc...

4. Conditional starting of services

For instance, alpine's init script only tries to do networking if it detects the apkovl or alpine_repo is a http(s)://* uri. I wonder if it would be possible for services to start other services inside the module conditionally.

What do you think? would this be a good approach? I also wonder if trees wouldn't be better in this scenario: Add a tree called initrd, add some services to it, copy it to the initramfs and start that tree when the system boots up in the initramfs, instead of using an isolated module service.

    vixalien 1. Re-usable functions

    It will work on 66 too. You can write your execute field with the language that you want. So you can e.g. do:

    Execute=(#!/usr/bin/sh
    exec 2>&1
    . /path/to/lib
    /path/to/script
    )

    vixalien 2. Shared environment
    Each sandir start with it own environment variable meaning /etc/66/environment for root and $HOME/.66/environment for regular user. You can define your environment variable by file on this directory.
    You can also have a script which parse the kernel commandline, write the result in some place and adapt your environment variable for the service. For instance, each service will contain

    Execute=(
       execl-envfile ${ImportFile} 
       /path/to/script
    )
    
    [Environment]
    ImportFile=/path/to/the/environment/file

    vixalien 3. Extensibility

    You're not forced to use module, you can use separated services activated or not depending of your environment variables.

    vixalien 4. Conditional starting of services

    I see no reason to not be able to do exactly the same on 66.

    Well, making this kind of stuff can be complicated to construct and force you to start a scandir inside the initramfs. Without this scandir you will not be able to start any service.
    I don't know if you will get a real benefit to do it, never tried. Some other part of 66 and Obarun need my attention before trying this kind of stuff. But well, i can help you on that if you lead the project.

    2 months later

    vixalien Re-usable functions

    No need. For the ebegin,eend,etc.. 66-yeller a.k.a. oblog is there for us.
    What does rc_add and similar functions do anyways? Plz let me know...

    Below are many references suggesting to create an instance of a module in the initramfs.
    Some [or all] of this can be pre-created at time of initramfs creation, for a "hostonly" initrd guaranteed to have minimal changes in the system to boot, like a desktop-user's laptop.

    vixalien not each script needs to parse the kernel cmdline each time

    Cmdline parsing is seldom needed, and most of the configuration can be stored in the itself, if not for the systemd-ism of dynamizing everything too much. For the few cases of requiring it [very rare for most server, desktop and embedded systems], let the serviec itself do it.

    If you really think it is needed....
    Make a cmdline-parse frontend script, which parses the cmdline and writes required output into /run/cmdline.env, which each frontend requiring the cmdline-parameters reads with execl-envfile. The cmdline-parse script sources all scripts in /etc/kargs-env/?*.*sh, where all scripts will write required variables into the cmdline.env file.
    OR
    Make a pre-init frontend which creates an instance of a module, say initramfs@ -> initramfs@sysinit, whose configure/configure script makes all required adjustments as needed [from cmdline, /proc /sys and all other data]. Yes, creating a module in the initramfs, but it will be fast and efficient, not as slow as you would think. But... you need to mount APIVFSs and do other such basic tasks BEFORE creating this module. [Not as complicated as it may 1st seem]

    vixalien Extensibility

    Modules are not limited by their isolation.
    In this case, some services go into separate modules, some don't be in any module.
    As I said, creating a module in the initramfs is the best solution for any dynamic setting.
    In this case, it is just a matter of ordering based on dependency.
    pbsplash just starts at the earliest after /dev/dri/* are ready, i.e. after udev[adm].
    bootchart is the earliest service before anything else, in this case.
    The [Regex] section of the module's frontend mainly comes into picture here, alongwith the configure/configure script.

    vixalien 4. Conditional starting of services

    Again, mostly modules. BTW, can you let me know what exactly is that feature in Alpine's int script you are talking about?

    vixalien What do you think? would this be a good approach? I also wonder if trees wouldn't be better in this scenario: Add a tree called initrd, add some services to it, copy it to the initramfs and start that tree when the system boots up in the initramfs, instead of using an isolated module service.

    Yes, but modules are more configurable, and flexible.

    The initrd-generator script just has to configure the modules [or just services] as needed at build-time, and also at runtime with modules [or a pre-init service, which is more acrobatics for less result]. Configuration is easier with modules, but not really necessary. Using just services will complicate the initrd-gen script.

    Plz do let me know what you want to do with an initrd anyway, other than LUKS/LVM/whatever and mounting the rootfs, after which the actual system does the rest of the work. In diskless mode or whatever, it is almost as simple as a non-initrd boot.

    Powered by Obarun