module/boot@ /service/local/firewall/local-iptables references
/usr/lib/iptables/scripts/iptables-flush
but that script does not exist.

The Arch iptables package provides /usr/lib/systemd/scripts/iptables-flush which could've been used instead if /usr/lib/systemd was not in your pacman.conf's NoExtract = list.
The script doesn't come from systemd but from the iptables package, which is from Arch. Maybe at the time the service was written that was the original location till arch made the systemd subdirectory. So either iptables needs repackaging by Obarun or the script adjusted to the current location. I would much rather not have any directory in the system labeled systemd.

The packman script prevents any such intruder to go into the system and totally break it. For onething it will replace the /sbin/init link and it will boot with systemd, but it will conflict with 2 tons of other stuff that systemd had no business to replace. It will also create a plethora of useless system users that will not be removed after you remove systemd and reinstall s6 (the 2 conflict, at /usr/bin/{init,poweroff,reboot,halt,shutdown} at least. So you really can't force install systemd till s6 is completely removed.

If you run:
pacman -Ql iptables | grep flush
/usr/lib/systemd/scripts/iptables-flush

so the script is there without systemd being present, but you are right the service is written wrong.

Till someone fixes it (boot@ -66serv) you can copy the service from /usr/lib/66/service/..... /etc/66/service and edit the environment link to the correct one. Otherwise give a little time for the devs to make adjustments. I would go to the git and write a correction and make a commit for the change, but the cleaner solution is to repackage iptables, and 45 other arch packages.

If arch made this move recently in this package they probably have done it across the board for many others. One can only find this out by making a some extensive arch installation and see what falls in that "hole". From my system it seems as the creation of those directories came Dec20, Jan and Feb. And there is tons of this crap in them.

On the other hand this is an environment definition, the package itself being an arch package, knows the correct definition of the location of the script. So I doubt it is producing an error.

Welcome to the war front! Whose side are you on?
Wow, that was really fast, many thanks for that!

I did some archaeology and the the iptables-flush script came in back in 2012 along with the systemd services. Since iptables-flush is used by these, I guess it made some sense to package it as /usr/lib/systemd/scripts/iptables-flush on a systemd-powered system -- along with all the other scripts called from systemd services.

So, from a technical point of view, by calling the iptables-flush script, module/boot@ /service/local/firewall/local-iptables has a dependency on Arch's packaging decision for the script, and this is /usr/lib/systemd/scripts/iptables-flush.
If there's a NoExtract= for /usr/lib/systemd/* then there's no script to call and hence local-iptables fails silently. As the script is still sensible (and a de facto requirement as being called by local-iptables regardless of the location), either the user should provide an alternative script to call whose location is defined by local-iptables / boot@ -66serv's config or some package should provide it (i.e., repackaging Arch's iptables or some other "catch-all" obarun package for such scripts). Repackaging iptables just for this one script (location) without having an otherwise strong dependency on systemd is a bit excessive in terms of maintenance...
If there's no such NoExtract=, then you'll end up with the (other) systemd cruft still in place, mostly useless.
It's a dilemma....

I think I will copy /usr/lib/systemd/scripts/iptables-flush to a more reasonable location and override boot@ -66serv's local-iptables in /etc/66/service/, also in order to do some more customizations....

Again, thanks for your efforts!
  • [deleted]

Hi.

That interesting because I do not see any of these files /usr/lib/iptables/scripts/iptables-flush and /etc/iptables/iptables.rules on others distro like Gentoo and Alpine Linux. I never enabled iptables on my side, but at least I know now that's not going to work apart from Obarun.

On the other hand I'm not in favor of 66 services depending on a systemd path.
Out of curiosity I sneaked a peak at artix iptables, there is no systemd directory, there is no script either. They just eliminated the entire thing. Back to obarun, /usr/lib/systemd/ has a load of crafty little things in it, it doesn't mean that systemd is here, just the name of the location of the scripts. So clearly, if all those packages that come from Arch are not repackaged by Obarun to relocate their scripts, if and when in fact come from upstream, the choice is to adjust the locations to /usr/lib/systemd if utilized in 66 runscripts.

But clearly it makes more sense to make such adjustments than eliminating scripts from upstream just because you don't know what to do with them. The runscript for runit is 2 lines. Environment being set for a service to run is of no importance, to runit. 66 sets environmental guidelines for the service to run in specific to the service. I am not sure whether scripts should be placed under /usr/lib or under /usr/share hierarchy. I think this is a major policy difference between arch and void, and I am afraid void is right.

Thank you for pointing this out though.
an another solution can be to write the stop command directly instead of calling a script:
[main]
@ type = oneshot
@ version = @ vers@
@ description = "Restore iptables rules"
@ depends = ( mount-rw )
@ user = ( root )
@ options = ( !log )

[start]
@ execute =
(
    if { 66-yeller -cdp local-iptables -1 /dev/console starts... }
    if -nt {

        execl-toc -e ${script_conf}
        iptables-restore ${script_conf}

    }
    66-yeller -fcdp local-iptables -1 /dev/console crashed!
)

[stop]
@ build = custom
@ shebang = "/usr/bin/bash -c"
@ execute =
(

    exec 2>&1

    66-yeller -cdp local-iptables -1 /dev/console stops...

    if ! type -p iptables &>/dev/null; then
      66-yeller -fcdp local-iptables -1 /dev/console "unable to find iptables program"
    fi

    while read -r table; do
        tables+=("/usr/share/iptables/empty-$table.rules")
    done <"/proc/net/ip_tables_names"

    if (( ${# tables[*]} )); then
        cat "${tables[@ ]}" | iptables-restore
    fi
)

[environment]
script_conf=!/etc/iptables/iptables.rules
I do like Eric's idea since for one the mechanism and the script hasn't changed in years so I consider it somewhat stable and it relieves the need to find a suitable (other) location for the /usr/lib/systemd/scripts/iptables-flush script or repacking Arch's iptables just for the script location. I'll go for this, thanks Eric!
One more thing: I think there's a modules-system missing in @ depends = (...) so that, e.g., the probably required kernel modules are loaded prior to local-iptables?

Since this required more than editing the service's environment, I edited /usr/lib/66/module/boot@ /service/local/firewall/local-iptables directly as I wasn't able to override local-iptables in /etc/66 while 66-enable: /usr/lib/66/module/boot@ was always used as source for populating /usr/lib/66/service/boot@ system (I chose 'system'). Maybe I did miss something obvious here how to override the boot@ module's local-iptables with my own in /etc/66?
I am not sure, Eric has the answer, but maybe the /etc/66/module is what is that you have to make a copy to and not /etc/66/service ...
Thanks for the suggestion, I tried /etc/66/module as well but that leads to not using any of the /usr/lib/66/module/boot@ module files, just the ones in /etc/66/module/, so there's no override here. This is consistent with the module documentation if I got it right. Putting it in /etc/66/service/ also does not result in it overriding the original boot@ module file, it's ignored.

So, as far as I understand, there's (currently?) no other way for overriding a module's service than to post-process the module's instance tree, e.g., /usr/lib/66/service/boot@ <name> in this case? The reason I'd like to have an override is that I can safely use 66-enable -F to get all the fresh stuff from a new/updated boot@ -66serv version while still "merging" my overrides into it...
I am not sure I am clear on what you have done, but did you copy the entire boot@ or just the services of interest? I think the entire thing has to be copied to etc even if changing one detail in one service file. So when you 66-enable -t boot -F boot@ ksks the entire module comes from /etc/66/module.

Maybe this is what you did and it is just no clear to me. And I may very well be wrong too..
If I make a full copy of the boot@ module to /etc/66/module/ it does work, you're right on this. If I try to just place one service, say local-iptables, somewhere in /etc/66 so that it overrides the same-named service of the module, it doesn't.

So, it seems to me there's (currently) no way of overriding only particular services of a module by placing a same-named service frontend somewhere in /etc/66. Disabling a module's service after instantiating the module to replace it with a same-named service from /etc/66/service doesn't work either. Hence, as I see it, the current solution is to copy over the whole module to /etc/66/modules or patch the module upfront prior to instantiating it (that's IMO easier and cleaner than patching the s6 translated service frontends).
I think that is how it works, you copy to etc/66/module/boot@ and then place/edit the service within this. Then enable and configure the entire module. Boot services must be within the boot module, most of them would make no sense to enable post-boot.
I am not sure about -iptables though, you may be right.
You can rename it into a service but edit the service file as an independent service instead of a part of the boot module.

Again I haven't done this, I am imagining this is how it works based on the experience I've had with 66.
The general idea and intent is that stuff in /usr are for a rolling distribution to regulate, so at each upgrade anything you have modified with the same filename may be over-written. in /etc default configurations are placed for you to edit, they should/will not be overwritten.

So you use /usr/lib/66 as a template of services, suggested, recommended, but 66 gives a priority to what the sys-admin has done. If nothing exists in /etc/66/ related to the service/module then it reads the default from /usr/lib/66. Same with user services, ~/.66/service has a priority to whatever is in /usr/lib/ or even /etc - you can define a user service in /etc a sys-admin, but if the user creates and modifies a copy of dbus-user or something in ~/.66 then this is what is used.
I kind of wanted the "best of both worlds", having rolling released /usr/lib/66/module/boot@ to get fresh updates but with specific overrides from /etc/66/<where ever>, automatically applied. I think I'm going to implement it with indeed modifying particular files in /usr/lib/66/module/boot@ and specifying them in pacman's NoUpgrade= so that I get notified and can merge whenever the files I modified got changed by an update.

Thanks again for your explanations and efforts, fungal_net!
@ fungalnet said right
You can overwritte a service which is a part of a module independently. You're forced to cp the entire module at /etc like you did, and change what you want inside it.
I just saw the commit f046e12 with the inlined iptables-flush script has landed in git, thanks for that, Eric!

One small note: I do think the double quotes in [stop] @ execute=('s body need to be -escaped, right?
no.
@ execute=(command)
@ execute=(
command)
@ execute=
(command)
@ execute=(
command
)
@ execute = ( command )
@ execute=          ( command)
@ execute=
(

command               )
and so on...
All these form are valid
Thanks Eric, but maybe that's only the case when using default execline as @ shebang "executor shell"?

Here's the 66-inservice output (redacted) of the local-iptables service copied to /etc/66/service/iptables:
Start script          :     if { 66-yeller -cdp local-iptables -1 /dev/console starts... }
                            if -nt {
                                execl-toc -e ${script_conf}
                                iptables-restore ${script_conf}
                            }
                            66-yeller -fcdp local-iptables -1 /dev/console crashed!
Stop script           :     exec 2>&1
                            66-yeller -cdp local-iptables -1 /dev/console stops...
                            if ! type -p iptables &>/dev/null; then
                              66-yeller -fcdp local-iptables -1 /dev/console "unable to find iptables program"
                            fi
                            while read -r table; do
                                tables+=("/usr/share/iptables/empty-$table.rules")
                            done <"/proc/net/ip_tables_names"
                            if (( ${# tables[*]} )); then
                                cat "${tables[@ ]}" | iptables-restore
                            fi

Then, 66-enable && 66-start works as expected but a 66-stop -v 4 iptables gives:
66-stop(src/lib66/ssexec_stop.c: ssexec_stop(): 236): tracing: stop atomic services ...
s6-rc: info: bringing selected services down
s6-rc: info: service iptables: stopping
s6-ipcclient: connected to /run/66/tree/0/root/servicedirs/s6rc-oneshot-runner/s
local-iptables: info: stops...
to: -c: line 6: syntax error: unexpected end of file
s6-rc: warning: unable to stop service iptables: command exited 2
66-stop(src/lib66/ssexec_dbctl.c: ssexec_dbctl(): 349): fatal: unable to stop services selection
When doing this with a -escaped shell body for [stop]'s @ execute=(...) block, like this (redacted)
Start script          :     if { 66-yeller -cdp local-iptables -1 /dev/console starts... }
                            if -nt {
                                execl-toc -e ${script_conf}
                                iptables-restore ${script_conf}
                            }
                            66-yeller -fcdp local-iptables -1 /dev/console crashed!
Stop script           :  
                             exec 2>&1
                         
                             66-yeller -cdp local-iptables -1 /dev/console stops...
                         
                             if ! type -p iptables &>/dev/null; then
                               66-yeller -fcdp local-iptables -1 /dev/console \"unable to find iptables\"
                             fi
                         
                             while read -r table; do
                                 tables+=(\"/usr/share/iptables/empty-$table.rules\")
                             done <\"/proc/net/ip_tables_names\"
                         
                             if (( ${# tables[*]} )); then
                                 cat \"${tables[@ ]}\" | iptables-restore
                             fi
I do not get the error
to: -c: line 6: syntax error: unexpected end of file
This lead me to think that I need to -escape the bash block.

Am I doing something (very) wrong here?
can please you post the output of
# 66-inresolve -t boot local-iptables
Hi Eric, thanks for coming back to this! Here's the relevant part of the output of my -escaped variant not having the error:
Real_exec_finish : 
fdmove -c 2 1
/usr/bin/bash -c "
 
     exec 2>&1
 
     66-yeller -cdp local-iptables -1 /dev/console stops...
 
     if ! type -p iptables &>/dev/null; then
       66-yeller -fcdp local-iptables -1 /dev/console \"unable to find iptables\"
     fi
 
     while read -r table; do
         tables+=(\"/usr/share/iptables/empty-$table.rules\")
     done <\"/proc/net/ip_tables_names\"
 
     if (( ${# tables[*]} )); then
         cat \"${tables[@ ]}\" | iptables-restore
     fi
  "
Assuming "Real_exec_finish" is verbatim what's executed, the -escaping is indeed needed for bash -c "<code>" with <code> having (unescaped) double-quotes in it.
maybe i found the trouble, please remove all you escaped character and replace
66-yeller -fcdp local-iptables -1 /dev/console "unable to find iptables"
by
66-yeller -fcdp local-iptables -1 /dev/console unable to find iptables
and tell us if it's work.
Hi Eric, here's the 66-inresolve output of the modified service that I tested:
fdmove -c 2 1
/usr/bin/bash -c "
    exec 2>&1
    66-yeller -cdp local-iptables -1 /dev/console stops...
    if ! type -p iptables &>/dev/null; then
      66-yeller -fcdp local-iptables -1 /dev/console unable to find iptables program
    fi
    while read -r table; do
        tables+=("/usr/share/iptables/empty-$table.rules")
    done <"/proc/net/ip_tables_names"
    if (( ${# tables[*]} )); then
        cat "${tables[@ ]}" | iptables-restore
    fi
 "
And guess what, it works :)
So, I guess the reasoning why this works is like 66-yeller simply prints all non-option args so we don't need to pass it just one message argument (by \"-escaping) and the other quoted strings are not concerned with word splitting, right?
yes, but i think i have a little problem with 66-yeller concerning the parse process of the command line. i need to check it.
Also, a bug exist on the @ execute field. Please add an exit command after the 66-yeller call like this
if ! type -p iptables &>/dev/null; then
      66-yeller -fcdp local-iptables -1 /dev/console unable to find iptables program
      exit 111
fi
Thanks Eric, good catch, I'll update it.

Powered by Obarun