If somewhere there is an inscription “Permission denied” or “Permission denied” - this is it, SELinux.

In MicroOS, almost everything is in containers. So you can figure it out a little bit without disabling SELinux.

View error messages:

ausearch -m AVC,USER_AVC

Then copy them to audit2allow for a hint on how to write the rules:

audit2allow -M local << EOF
type=AVC msg=audit(1234.332:155): avc: denied { read } for pid=1 comm="systemd" name="poweroff.timer" dev="overlay" ino=14326 scontext=system_u:system_r:init_t:s0 tcontext=unconfined_u:object_r:admin_home_t:s0 tclass=file permissive=0
type=AVC msg=audit(1235.916:182): avc: denied { execute } for pid=1481 comm="(t_run.sh)" name="first_run.sh" dev="sda1" ino=390 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:unlabeled_t:s0 tclass=file permissive=0
type=AVC msg=audit(1236.103:208): avc:  denied  { open } for  pid=1 comm="systemd" path="/etc/systemd/system/poweroff.timer" dev="overlay" ino=14326 scontext=system_u:system_r:init_t:s0 tcontext=unconfined_u:object_r:admin_home_t:s0 tclass=file permissive=0
type=AVC msg=audit(1237.700:45): avc:  denied  { execute_no_trans } for  pid=1232 comm="(t_run.sh)" path="/cloud/system/first_run.sh" dev="sda1" ino=390 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:unlabeled_t:s0 tclass=file permissive=0
type=AVC msg=audit(1238.028:1018): avc:  denied  { connectto } for  pid=9419 comm="go-avahi-cname" path="/run/dbus/system_bus_socket" scontext=system_u:system_r:container_t:s0:c620,c905 tcontext=system_u:system_r:system_dbusd_t:s0-s0:c0.c1023 tclass=unix_stream_socket permissive=0
type=USER_AVC msg=audit(1239.616:1869): pid=867 uid=499 auid=4294967295 ses=4294967295 subj=system_u:system_r:system_dbusd_t:s0-s0:c0.c1023 msg='avc:  denied  { send_msg } for msgtype=method_call interface=org.freedesktop.DBus member=Hello dest=org.freedesktop.DBus spid=15063 scontext=system_u:system_r:container_t:s0:c620,c905 tcontext=system_u:system_r:system_dbusd_t:s0-s0:c0.c1023 tclass=dbus permissive=0 exe="/usr/bin/dbus-daemon" sauid=499 hostname=? addr=? terminal=?'
type=USER_AVC msg=audit(1240.455:3529): pid=867 uid=499 auid=4294967295 ses=4294967295 subj=system_u:system_r:system_dbusd_t:s0-s0:c0.c1023 msg='avc:  denied  { send_msg } for msgtype=method_call interface=org.freedesktop.Avahi.Server member=GetHostNameFqdn dest=org.freedesktop.Avahi spid=26468 tpid=865 scontext=system_u:system_r:container_t:s0:c620,c905 tcontext=system_u:system_r:avahi_t:s0 tclass=dbus permissive=0 exe="/usr/bin/dbus-daemon" sauid=499 hostname=? addr=? terminal=?'
type=USER_AVC msg=audit(1241.936:4020): pid=867 uid=499 auid=4294967295 ses=4294967295 subj=system_u:system_r:system_dbusd_t:s0-s0:c0.c1023 msg='avc:  denied  { send_msg } for msgtype=method_return dest=:1.6155 spid=865 tpid=29848 scontext=system_u:system_r:avahi_t:s0 tcontext=system_u:system_r:container_t:s0:c620,c905 tclass=dbus permissive=0 exe="/usr/bin/dbus-daemon" sauid=499 hostname=? addr=? terminal=?'
type=USER_AVC msg=audit(1242.396:4015): pid=867 uid=499 auid=4294967295 ses=4294967295 subj=system_u:system_r:system_dbusd_t:s0-s0:c0.c1023 msg='avc:  denied  { send_msg } for msgtype=method_call interface=org.freedesktop.Avahi.Server member=GetHostNameFqdn dest=org.freedesktop.Avahi spid=29827 tpid=865 scontext=system_u:system_r:container_t:s0:c620,c905 tcontext=system_u:system_r:avahi_t:s0 tclass=dbus permissive=0 exe="/usr/bin/dbus-daemon" sauid=499 hostname=? addr=? terminal=?'
type=AVC msg=audit(1703137871.316:156): avc:  denied  { ioctl } for  pid=1 comm="systemd" path="/etc/systemd/system/poweroff.timer" dev="overlay" ino=35184 ioctlcmd=0x5401 scontext=system_u:system_r:init_t:s0 tcontext=unconfined_u:object_r:admin_home_t:s0 tclass=file permissive=0
type=AVC msg=audit(1703372068.827:2596): avc:  denied  { write } for  pid=20749 comm="systemd-helper" name="system_bus_socket" dev="tmpfs" ino=1475 scontext=system_u:system_r:snapperd_t:s0 tcontext=system_u:object_r:container_file_t:s0 tclass=sock_file permissive=0
EOF

The generated local file.te can be adjusted at will. Then you need to compile it:

checkmodule -M -m -o local.mod local.te
semodule_package -o local.pp -m local.mod

And install (applies constantly):

semodule -i local.pp

Only audit2allow still needs to be installed:

transactional-update pkg install policycoreutils-python-utils
reboot

In general, it is clear that this approach is slightly better than completely disabling SELinux, but worse than the “correct” task of rights. Now the permissions look like unconfined_u:object_r:unlabeled_t:s0. In theory, you will need to deal with the current policies, and based on this, you will need to add new files to some ready-made entities or you need to start your own.

As a result

And when all this gets boring after many iterations, we just turn it off:

echo > /etc/selinux/config <<EOF
SELINUX=permissive
SELINUXTYPE=targeted
EOF
reboot

Why? For almost every docker container, the rules need to be finalized. Plus, cockpit is in packages, but there are no rules for it (you can’t even log in). And in the last installation, did something break at all (in the system itself?) and their own rules were not applied:

# semodule -i local.pp
libsemanage.semanage_module_info_set_lang_ext: Language extensions =  is invalid.
libsemanage.semanage_module_info_set_lang_ext: Language extensions =  is invalid.
libsemanage.semanage_module_info_set_lang_ext: Language extensions =  is invalid.
semodule:  Failed on local.pp!

So SELinux is not for home yet, even if we are going to run user applications only in containers.

And this also may not help if the etc/default/grub file contains enforcing=1 (you need to change it to 0 and regenerate it with the sudo transactional-update grub' command.cfg; reboot).