S6 init system with s6-66 service manager in Antix-init-diversity spin

OK lets try to set up rc.local

nano /etc/66/rc.local
add the lines
#!/usr/bin/sh
modprobe uinput

Now , how do I set this LOCAL=!yes
I found from the Gentoo forum that it is set in /etc/66/conf/boot.conf
but that was for s6-rc.
In my Antix with s6-66 there is no boot.conf file in /etc/66 ?
So lets try without first… does not work

It seems that in s6-66 one does not edit the boot.conf file, one uses

66 configure -e nano boot@system

so I do that and change LOCAL=!no to yes

reboot and
No, it still does not load the uinput module?

I think I need to do
66 reconfigure boot@system

after that I reboot and the boot hangs on
local-rc: info launch rc.local script

So it invoked the script , but there is something wrong?

Give up and put uinput in /etc modules
That does not work either ?

I have to do 66-recofigure boot@system again
and
set LOCAL=!no
set MODULE_KERNEL=!yes
and do
66 reconfigure boot@system
reboot
and then it works…

The uinput module is loaded when it boots.

I have spice-vdagentd running, but there is an additional daemon called
spice-vdagent which is supposed to run every time a user starts an X session.
That doe snot work in Antix… I start it by hand.
What I thought might be worth a try is to start spice-vdagent as a user service
under 66.
I read that a user has to be given permission ?

Afterthought:
I think I know why the rc.local script hung on boot.
The #!/usr/bin/sh line
has to be he very first line… not after the comments
Stupid me.

3 Likes

OK, now it works

root@antix-init-diversity:/home/nevj# lsmod | grep uinput
uinput                 20480  0

The /etc/66/rc.local file has to be like this

#!/usr/bin/sh

# Copyright (c) 2015-2021 Eric Vidal <eric@obarun.org>
# All rights reserved.
#
# This file is part of Obarun. It is subject to the license terms in
# the LICENSE file found in the top-level directory of this
# distribution.
# This file may not be copied, modified, propagated, or distributed
# except according to the terms contained in the LICENSE file.
#
# Default rc.local for Obarun; add your custom commands here.
#
# This is run at the end of the boot sequence.
# This file is declared as oneshot service on 66, do not try to launch
# any daemon with this file.

# WARNING: Do not forget to set the shebang.

modprobe uinput

and I have to do

66 configure -e nano boot@system
and set 
LOCAL=!yes
then 
66 reconfigure boot@system

I left MODULE_KERNEL=!yes too, in case I wanted to use /etc/modules, but I deleted uinput from /etc/modules… dont want to load it twice!

S0 what have I learnt …
s6-66 manages more things than starting daemons. It can turn on of off various actions that occur during a boot, for example

  • mount files in fstab
  • mount SWAP
  • use /etc/modules
  • use /etc/modules.d
  • use /etc/66/rc.local

I think that is OK, provided it keeps to things that occur during boot… We dont want it managing everything in a running system the way systemd attempts to
do.

And I re-learnt to put #! on the first line.
That means I did not learn it properly in the first place.

3 Likes

Now , I still have not swallowed this message properly.
The modules documentation is here
https://web.obarun.org/software/66/latest/66-module-usage.html
It says
" As module is a set of services, when you start it, several services may be started."
and
" A module is a instantiated service and can be managed like any other instantiated services. For intance, to start it
66 start foo@b"

But what is an instantiated service?
That is documented here
https://web.obarun.org/software/66/latest/66-instantiated-service.html
and it says
" An instantiated service file is of the same syntax as decribed in the frontend document for any other service. It can be any type of service. However some differences exist :

  • the name of the file needs to be appended with an @ (commercial at) character.
  • every value replaced in an instance file needs to be written with @I."
    and it gives an example of a frontend for the instantiated service tty@

There is more on modules here
https://web.obarun.org/software/66/latest/66-module-creation.html
it says
" A module is an instantiated service. It works the same way as a service frontend file but allows the user/admin to configure a set of different kind of services before executing the parse process. Also, the set of services can be configured with the conjunction of a script called configure which can be made in any language.

This allows one to pre-configure a set of parameters or other services for special tasks without knowing the exact target of the module. The best example is the module for booting a machine. Each machine is different and the set of services need to be adaptable as much as possible for different kinds of machines during boot; e.g booting a container.

Additionally, a service of type ‘module’ can be likened to a sandbox. Services within a module are isolated from those outside it, and vice versa."

OK, I am getting a picture. A module is special. It is more configurable than a normal classic service or a tree of classic services, and it is isolated.
but
“instantiated” has me confused.

  • " A module is an instantiated service"
  • " module is a set of services"
  • " A module can contain instantiated service."

So questions
Why are some services “instantiated” , what does it do that is different from a classic service and when should instantiated be used?

How are modules related to trees?

3 Likes

Good questions @nevj
You might want to read on what systemd defines as “instantiated services”.

I assume 66 can achieve similar functionality.

Maybe Eric can shed more light on this

3 Likes

Taking an exemple from scratch, the tty service.
At base, to start a tty, we need to do

#  agetty -J 38400 tty7

here the daemon agetty is launch to control tty7 device. So, i can go to this tty7 is logon. Now if i want another tty, for instance 5, i need to do

# agetty -J 3800 tty5

This is the exact same line of code excepting the number at the end to target the desire tty.

Well come back to my service, i create the frontend file /etc/66/service/tty1

[main]
@type = classic
@description = "My first tty service for the tty5"
@version = 0.0.1
@user = ( root )

[start]
@execute = ( agetty -J 38400 tty1) 

This is good enough to be able to do

# 66 start tty1

The service should be running. Now, if i want to do the same for the tty7, i need to create one more file /etc/66/service/tty7 with the same contents as tty5 but replacing the number 5 by 7 as follow

[main]
@type = classic
@description = "My first tty service for the tty7"
@version = 0.0.1
@user = ( root )

[start]
@execute = ( agetty -J 38400 tty7) 

So, good but if i want the tty1 and 2 and 3, should i create one file for each one? This is where instantiated service come in place. Instantiated service are modified copy of original template for a service. In short (very short), that’s just “sed” command applied at creation time(A.K.A. parsing for 66) of the service.

Users need to be able to specify what they want to change to the original service, for this purpose we use a special syntax name to make distinction between the original file and the modified copy.

In short original@copy, where original is the name of the original frontend file and copy the name of the instantiated service.

In our case, it will be tty@. Naming my frontend file with that name with ‘@’ character at the end permit to 66 to recognize it as an original service file for future instantiated service.

Now, i need a way to specify to 66 what i want to change from the original frontend file (tty@ frontend file in our example). Do do so, on 66, i will employ the reserved string ‘@I’ inside my tty@ frontend file.

Well, my /etc/66/service/tty@ contents is now

[main]
@type = classic
@description = "My first tty service for the @I"
@version = 0.0.1
@user = ( root )

[start]
@execute = ( agetty -J 38400 @I)

Here i instruct 66 the place to make changes with the user request. The user request is given by the complete name of the instantiated service like so,

# 66 start tt@tty10

With this command, i request to 66 to create an instantiated service of the original frontend file tty@, to change the @I found inside the frontend by the name of copy, which is tty1 for us, and continue to do what it need to do to start the service.

So, when 66 keep information of the service before starting the service, from its point of view the frontend file of the service is

[main]
@type = classic
@description = "My first tty service for the tty10"
@version = 0.0.1
@user = ( root )

[start]
@execute = ( agetty -J 38400 tty10)

66 just has replaced the ‘@I’ found by tty10.

This way, we have one frontend file for many services.

no sure to understand the question here. Related as any other service. But what mean related for you :slight_smile:

4 Likes

The way I understand trees vs modules:

A module is a service bundle that can belong to tree.

Trees & modules share similarities (like essentialy s6-rc bundles they would be composed by a group of atomic services), but their purpose & usage is different.

Are these assumptions right @obarun ?

3 Likes

Tree can be view as e.g. an activities classification. For instance, on my system i have a tree named virtual. This tree contains service concerning virtualization like dockerd, libvirtd. So, when i need to work on a VM on through docker image, i start my tree virtual.

A service with a type a module permit to change the behavior of the service regarding the request of an user through environment variable. In function of the value of the environment variable the behavior will change.
For instance, the boot-user@ service allow the user to use or not an user tracking process (consolekit, seatd, …), to create or not the XDG_RUNTIME_DIR, to use or not a login manager, depending of the variable definition given by the user.

Hope i’m clear

4 Likes

Very clear thank you.
I was thinking of putting docker in a separate tree… that is a good example of a service that is only needed at certain times.

The example of an instantiated service is very clear too

I have to start thinking of module as a type .
as @ProwlerGr says

Type is about how a service is used.

The ability to to change its behaviour is the key module feature.
A module can be one service or a bundle of services.
A module is instantiated… does that mean all services in it are separately instantiated? or do we instantiate the module itself?
Looks like the latter, from the boot-user@ example

There are a number of new concepts to learn here. I have never looked at systemd, so I dont have any background to lean on.
Runit does not have instantated services or trees or the type concept. It is all about individual (atomic) services. Sysvinit does have runlevels, which are a bit like trees.

3 Likes

The module itself is intantiated. Service inside the module can be any type instantiated or not.
Any types of services can be instantiated, however a service of type module type is forcefully an instantiated service.

Instantiated service are concept used by others service manager where the concept of module is 66 specific feature. Module are very powerful and flexible, but maybe a little complex to understand at first start.

4 Likes

@ProwlerGr @obarun

Experimenting with a user service

I read that one needs to have a scandir for the user, and in order for this scandir
to be created properly there needs to be at least one user tree.
So I made a user tree, and a scandir entry, running as nevj

$ 66 tree create spice-tree
tree: info: Created successfully tree: spice-tree
tree: info: Permissions rules set successfully for tree: spice-tree

nevj@antix-init-diversity:~
$ 66 scandir create
scandir: info: create scandir /run/66/scandir/1000 ...

Then I put a frontend for spice-vdagent in ~/.66/service

nevj@antix-init-diversity:~
$ ls ~/.66/service
spice-vdagent

and tried to enable the tree

nevj@antix-init-diversity:~
$ 66 tree enable spice-tree
tree: info: Enabled successfully tree: spice-tree

Then look at it

$ 66 tree status spice-tree
Name        : spice-tree
Current     : no
Enabled     : yes
Allowed     : nevj
Groups      : user
Depends     : None
Required by : None
Contents    : None

It has no contents?
How do I add spice-vdagent to the tree?
Do I maybe need to parse it?

nevj@antix-init-diversity:~
$ 66 parse spice-vdagent
parse: fatal: unable to parse file of service: spice-vdagent

No that does not work. Why not? There is a frontend for it in ~/.66/service.

Do I need to start the tree?

nevj@antix-init-diversity:~
$ 66 tree start spice-tree
tree: fatal: scandir: /run/66/scandir/1000 is not running

There is no entry in the scandir for spice-vdagent

nevj@antix-init-diversity:/run/66/scandir/1000
$ ls
fdholder  oneshotd

I thought parse was supposed to put it there, … but parse does not work?

I am stuck again.

Here is the error log from the parse attempt

nevj@antix-init-diversity:/run/66/scandir/1000
$ 66 -v 4 parse spice-vdagent
parse: (parse_frontend(): 126): tracing: parse service: /home/nevj/.66/service/spice-vdagent
parse: (parse_frontend(): 141): tracing: read frontend service at: /home/nevj/.66/service/spice-vdagent
parse: (parse_split_from_section(): 76): tracing: parsing section: main
parse: (parse_split_from_section(): 161): tracing: parsing key: @type
parse: (parse_store_g(): 25): tracing: storing key: @type
parse: (parse_split_from_section(): 161): tracing: parsing key: @description
parse: (parse_store_g(): 25): tracing: storing key: @description
parse: (parse_split_from_section(): 161): tracing: parsing key: @version
parse: (parse_store_g(): 25): tracing: storing key: @version
parse: (parse_split_from_section(): 161): tracing: parsing key: @user
parse: (parse_store_g(): 25): tracing: storing key: @user
parse: (parse_store_main(): 328): warning: unable to use the service -- permission denied
parse: (parse_store_g(): 33): warning: unable to store value of section: main
parse: (parse_split_from_section(): 208): warning: unable to store resolve file of: spice-vdagent
parse: (parse_frontend(): 233): fatal: unable to parse file of service: spice-vdagent

Permission denied.
Why?

1 Like

66 -t spice-tree enable spice-vdagent

Can you post the contents of your user frontend file?

1 Like

Minimal file

[main]
@type=classic
@description="spice-vdagent daemon"
@version=0.0.1
@user=(root)

[start]
@execute=(
    foreground { mkdir -p /run/spice-vdagent }
    foreground { chmod 0755 /run/spice-vdagent }
    /sbin/spice-vdagentd -d
)

I tried your command

$ 66 enable -t spice-tree spice-vdagent
enable: usage: 66 enable [ -h ] [ -S ] service...

activate services at the next boot

options:
   -h: print this help
   -S: enable and start the service immediately

Seems we have a syntax problem here?
It does not have a -t option?

Leave out -t option

$ 66 enable spice-vdagent
parse: fatal: unable to parse file of service: spice-vdagent
1 Like

Sorry I pasted the wrong command before, corrected now.

Found another problem looking at it now…
User $PATH$ needs to be updated to include 66 locations.

Thanks. Will be back onto that tomorrow.

@obarun
I understand there would be more efficient ways (or mistakes in this guide), keen to get your feedback.
I’ll admit this is my first attempt to get a user service working

@nevj just tracing my steps below:
Step 1: You need to update your user $PATH$ in order to be able to 66 user services.
For now lets just update your bashrc file:

nano ~/.bashrc

go to lines 115-116 & replace them with the below contents

echo $PATH | grep -Eq “(^|:)/sbin(:|)” || PATH=$PATH:/sbin:/lib/execline/bin:/usr/lib/execline/bin:/usr/libexec
echo $PATH | grep -Eq “(^|:)/usr/sbin(:|)” || PATH=$PATH:/usr/sbin:/lib/execline/bin:/usr/lib/execline/bin:/usr/libexec

Step 2
Create frontend /etc/66/service/spice-vdagentd with contents

[main]
@type=classic
@description=“spice-vdagentd daemon”
@version=0.0.1
@user=(root)
[start]
@execute=(
execl-toc -d /run/spice-vdagentd -m 0755
/usr/sbin/spice-vdagentd ${Args}
)
[environment]
Args=-x -d

& start with

sudo 66 start spice-vdagagentd

Step 3
Create your user scandir & start it:

66 scandir create
66 scandir start

Step 4
Create frontend ~/.66/service/spice-vdagent with below contents (substitute @user with your username):

[main]
@type=classic
@description=“spice-vdagent daemon”
@version=0.0.1
@user = ( antix )
[start]
@execute=(
/usr/bin/spice-vdagent -x
)

& start as user with

66 start spice-vdagent

Step 5 (optional)
Create tree called spice-tree & add spice-vdagent to it.

66 -t spice-tree start spice-vdagent

OK, thanks, that is a complicated PATH

So I dont need to make a user tree to operate a user service?

Unfortunately it needs to be updated or the user will be unable to run a scandir for his services.

No you can have it on the global tree, which is enabled by default

2 Likes

That’s correct. Howerver, using 66 with regular user reacts as exactly as it do with root user. That means that any first invocation of any commands of 66 will create for you the necessary directory.
In short it will create and populate the ~/.66 directory and create the global tree for an user.

So, you created the tree and enabled it, but at default the tree will be empty. You just created tree to handle “activity” (if i keep the previous analogy). Now you need to associated a service to that tree. To do so you need to associated a service to the tree using e.g. 66 -t spice-tree enable spice-vdagent.

The message is very clear. You don’t set properly the field @user to be able to use your service as regular user. The @user frontend field tell to 66 what user can use the service.

66 provide two different way to accomplish this.

  • You can declare @user=(nevj). In that case, only the nevj account can deal with your service even root will be denied to use this service, neither other regular account will be denied.
  • You can declare @user=(user). In that case any valid regular account will be authorized to use the service. For 66, the term user means : “Allow any regular account on the system to deal with that service”.

Now, you have two different place to store your frontend file for an user. In reality you have three but the first one /usr/share/66/service/user is dedicated for the packager.

  • The first directory to place your frontend is /etc/66/service/user. Note the difference with root service which is placed at /etc/66/service. A frontend file for a regular must be placed inside /etc/66/service/user. Putting it at /etc/66/service directory will not work.
  • The second directory is $HOME/.66/service. So, regular user do not need to make changes on root directory like /etc

If you don’t respect these path, 66 will be unable to find your regular user frontend file.

That is very specific to Debian user cause of the mess of the execline sotfware installation (Debian dev refuse to deal with it correctly). it should not necessary to update your PATH on a classic linux system.

Now, how i start my scandir for a regular user?
Some explanation is needed. First at all, each regular account must have his own scandir to start his services. Services from root and service from user are completely independent from each other. If you look at /run/66/scandir/ you will see different directory like 0, 1001, 1002. So, each user (regular or root) will get his own scandir directory. The name of the directory (e.g. /run/66/scandir/0) correspond to the uid of the user.

So, service from /run/66/scandir/1000 don’t know anything about service at /run/66/scandir/1001 even on /run/66/scandir/0. That also means that the user 1000 can not deal with service from user 1001. Even root can not handle regular service and the contrary is also true, regular user cannot deal with root service.

So,

this command will effectively start a scandir for the user. But you can be shorter doing directly 66 scandir start. If the scandir is not yet created, 66 will first launch the 66 scandir create command for you.

When you do that, you will see that the 66 scandir start command hold the terminal and this is expected. You have two choices, you can do

% $(66 scandir start &)&

This will put the scandir program to the background and so you get again the control of the terminal.
Or, you just open a another terminal to be able to start your service.

Now, you should be able to start any regular user service with the classic 66 start command.

Yes, this is mandatory. Like i said, each account get its own scandir.

3 Likes

I get it. I can set either a specifuc user or all users.
I did not pay attention to the @user parameter

1 Like

I wondered what /etc/66/service/user was for.
I used ~/.66/service

They both make sense now. Thank you.