cinit - Configuring
===================
Nico Schottelius <nico-cinit__@__schottelius.org>
0.1, for cinit 0.3, Initial version from 2005-05-28
:Author Initials: NS


This documentes describes how to configure cinit.
You should already have cinit installed, otherwise read
"cinit - Installing" first.


Less is more
------------
In contrast to a lot of other init system configurations, the
cinit configuration is not a "catch all", but more a "minimalistic"
configuration: I don't think it's wise to include support for
exotic configurations and a lot of if/else combinations in an init
system configuration. These if/else should be solved at the configuration
time, *not* everytime at boot!


General configuration layout
----------------------------
Cinit uses the <<<cconfig>>> configuration syntax, which means that
the configuration is kept as simple as possible. The following
sections will show you what that means.

The cinit configuration consists of
- a special configuration directory
- and the service definitions.

Paths
-----
Normally the configuration is kept below '/etc/cinit'
(though you can change this before compiling in conf/cinit_dir).

The full description of the path layout of cinit and how to change it
can be found in 'paths.text'.

Conf
----
The special configuration directory is normally called `conf/`
(defined at compile-time in `conf/c_confdir`).

For all executables into this directory apply the same rules as mentioned
below in "Execution: on and off": Appened .params specifies parameters,
appended .env specifies environment.


conf/last
~~~~~~~~~
This is the last part that will be executed. After it has finished, cinit
will halt, power-off or reboot your machine.

You can use it for whatever task to accomplish (as most things of cinit), but
the idea behind it is to use it for cleaning up things that are not covered
by the off parts of the services. This maybe swapoff (although this is an unecessary
call before poweroff, imho and even if needed this could be handled within the
off part of the same services that enabled it) or `umount -a` for everything
manually mounted and not unmounted yet.


conf/sleep_before_kill
~~~~~~~~~~~~~~~~~~~~~~
This file contains just one line: The number of seconds to sleep after SIGTERM was sent
to every remaining process before sending SIGKILL to all processes. If this file
is unreadable or not existent, cinit will fall back to the value compiled in
(which was specified at build time in conf/sleep_kill).


Services
--------
cinit is service based. Other init systems use shell
scripts (for instance /etc/rc, /etc/init.d/rc as starters
and /etc/rc*.d/* as "service definitions").

'current-init-problems.text' explains why cinit does *not*
use nor recommends the use of shell scripts.

A service is simply a directory. This directory contains information about

- what should be started when starting the service
- what should be started when stoping the service
- what dependencies the service has
- whether to restart it, when it exits


Full service definition
~~~~~~~~~~~~~~~~~~~~~~~
. A service consists of
   - a base directory (like /etc/cinit/svc/mount/root/)
   - dependency configuration (`needs` and `wants`)
   - start/stop programs (`on` and `off`)
   - respawn flag (`respawn`)


Base directory
^^^^^^^^^^^^^^
You can create the base directory everywhere below /etc/cinit/svc.
You may and it is recommened to create a directory structure
(see 'example-directory-structure.text').


Dependencies
^^^^^^^^^^^^
The subdirectories

- `wants`
- and `needs`

contain the dependencies for the service.

Read 'dependencies.text' for more information.


Respawning
^^^^^^^^^^^
If you create the empty file 'respawn' (adjustable via conf/c_respawn)
the service will be restarted after it exits.

--------------------------------------------------------------------------------
# Tell cinit to respawn the eth0.udhcpc service
touch /etc/cinit/svc/network/eth0.udhcpc
--------------------------------------------------------------------------------


Execution: on and off
^^^^^^^^^^^^^^^^^^^^^
When a service starts, the file `on` in the service
directory is executed. It is ok, if this file is not existing.
When a service stops, the file `off` in the service
directory is executed.

The file with the extension `.params` is used to specify the arguments
to pass. Each line contains exactly one parameter.

The file with the extension `.env` is used to specify the environment
to pass. Each line contains exactly one variable definition in the form
'variable=value'.

. The following six files are possibly used on starting/stoping:
   - ./on            (the program called on startup)
   - ./on.params     (the parameters to pass to the program, see conf/c_params)
   - ./on.env        (the environment to pass to the program, see conf/c_env)
   - ./off           (the program called when shutting down the service)
   - ./off.params    (the parameters to pass to the program)
   - ./on.env        (the environment to pass to the program)

Some examples:
----------------------------------------------------------------------
   /etc/cinit/svc/init:
      ./wants -> services it wants
      ./needs -> services it needs
----------------------------------------------------------------------

A more or less normal service without dependencies:
----------------------------------------------------------------------
   /etc/cinit/testsvc:
      on       -> link to program
      on.param -> parameters to program
      respawn  -> restart it
----------------------------------------------------------------------
 
A service with all options used:
----------------------------------------------------------------------
   /etc/cinit/fullsvc:
      on          -> program to start when switching on
      on.params   -> parameters to pass to start program
      on.env      -> environment to pass to start program

      respawn     -> respawn service

      off         -> program to start when switching off
      off.params  -> parameters to pass to stop program
      off.env     -> environment to pass to stop program

      wants/*     -> services it wants before starting (non-critical ones)
      needs/*     -> links to needed services (critical!) before starting
----------------------------------------------------------------------


Profiles
--------
Profiles allow you to define different startup scenarios and select
those before bootup. Read 'profiles.text' for more information about
profiles.

The profile support was added in cinit-0.0.6.


Service execution order
------------------------
The first service executed is '/etc/cinit/svc/init'.
If a profile is selected '/etc/cinit/svc/`profilename`' is used
instead.

Cinit builds a full service dependency tree through the `wants`
and `needs` of the first service and its dependencies
(recursively).

After the tree is generated, cinit begins to start the services
at the end of the tree. These services have no `needs`.

If you manage to create circular dependencies your system will not startup.
You can verify the correctness your configuration with the script
`cinit.check.config`.


Hints
-----

Service executing / parameters
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The on and off files can and should be links to the programs you want
to execute instead of a shell script. This way you save yourself the overhead
of loading a shell. The speed enhancement is very big if you have shells
like bash installed as /bin/sh (which is *not* senseful anyway, I would
recommend dash or ksh for /bin/sh).

The on.params and off.params files could also be links to system configuration:

Assume the service is called local-tuning/keyboard.
The service could look like this:
----------------------------------------------------------------------
   on -> /bin/loadkeys
   on.params -> /etc/sys/keyboard.mapping

   And /etc/sys/keyboard.mapping would contain only the string
   "dvorak" (or "de-latin1" or "sg-latin1" or ...).
----------------------------------------------------------------------


Daemons
~~~~~~~~
Daemons are programs that go away to the background (using fork()) after
start).

The fork-away strategy seems to be some illness introduced by traditional
init systems, that are dependent on the fact, that a process exits on
startup.

cinit in contrast remembers the process ID (pid) of the services it
restarts (those with `respawn` enabled).

So when the daemon fork()s away and the parent process exits it looks to
cinit like the watched service died and cinit will restart it.

Happily, most processes can be taught not to go to background.
Some processes even do that by default and very less are broken that
one cannot tell them not to background.

A list of known processes that are normally used in respawn
processes can be found in 'daemons.backgrounding.text'.

If your process is not listed in `daemons.backgrounding.text', 
check the documentation of your daemon program, if may have a
switch to disable forking.

But, with a small hack it is even possible to respawn those broken processes:

We start a program, that
   - starts the daemon,
   - monitors the pidfile of the daemon,
   - waits until that pid does not exist anymore
   - and then exits.

Such a program is included into the cinit source tarball,
though I do not recommend using it. The better way is to implement
non forking mode into your process.

The name of the program (actually a shell script) is 'cinit.wait.for.daemon'.

You can use it as the `on` part of a service and add

   - the pidfile,
   - the process binary
   - and the process parameters

to `on.params`.

Thus the service could look like:
----------------------------------------------------------------------
   svc-broken-daemon/
      on -> /sbin/cinit.wait.for.daemon
      on.params:
         /var/run/apache.pid
         /usr/packages/apache-2.0.51/bin/httpd
         -DSSL
----------------------------------------------------------------------
(This is not a so good example, because Apache supports non-forking mode).

Be aware: This is just a hack, first try to avoid backgrounding
and you won't need this hack!


Logging
~~~~~~~
Currently there's no special logging support.
When a process writes to stdout, it will be displayed on
the same stdout cinit is connected to.

In newer versions cinit (perhaps cinit-0.4) will also support logging
stdout and stderr of a service.


How to migrate your old init-system configuration to cinit
----------------------------------------------------------
This is highly dependent on your actual system, your system
configuration and your own ideas.

Cinit is able to replace all other init systems I know about.

So the only question is "How to do it?".

There are some hints on how to migrate to cinit in general and also
some os specific help in the file 'migrating-init-systems.text',


Debugging the configuration
----------------------------
Use `ls -lR /etc/cinit` or one of the tools found in contrib+tools/.


Examples
--------
Currently there are some example configurations available
at http://unix.schottelius.org/cinit/samples/cinit-0.3/, sorted
by host on which they are created.

In near future, there will also be a file name configuration.example.text,
which will lead you to a sample configuration.


References
----------
+ [[[cconfig]]] http://nico.schotteli.us/papers/linux/cconfig/
