#!/bin/sh # This scripts is borrowed from distrobuilder. # awk '/content := `/ {match($0, /.*`([^`]*)/, l); print l[1]; a=1; next} /^`$/ {a=0} a {print $0}' < main.go # Probably, it will need to be updated from time to time. [ -h /sbin/init ] || exit 0 generators_dir=/etc/systemd/system-generators mkdir -p "$generators_dir" cat > "$generators_dir"/lxc <<'@@@' #!/bin/sh # NOTE: systemctl is not available for systemd-generators set -eu ## Helper functions # is_lxc_container succeeds if we're running inside a LXC container is_lxc_container() { grep -qa container=lxc /proc/1/environ } # is_lxd_vm succeeds if we're running inside a LXD VM is_lxd_vm() { [ -e /dev/virtio-ports/org.linuxcontainers.lxd ] } # is_in_path succeeds if the given file exists in on of the paths is_in_path() { # Don't use $PATH as that may not include all relevant paths for path in /bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin; do [ -e "${path}/$1" ] && return 0 done return 1 } ## Fix functions # fix_ro_paths avoids udevd issues with /sys and /proc being writable fix_ro_paths() { mkdir -p /run/systemd/system/$1.d cat <<-EOF > /run/systemd/system/$1.d/zzz-lxc-ropath.conf [Service] BindReadOnlyPaths=/sys /proc EOF } # fix_nm_force_up sets up a unit override to force NetworkManager to start the system connection fix_nm_force_up() { # Check if the device exists [ -e "/sys/class/net/$1" ] || return 0 # Check if NetworkManager exists [ "${nm_exists}" -eq 1 ] || return 0 cat <<-EOF > /run/systemd/system/network-connection-activate.service [Unit] Description=Activate connection After=NetworkManager.service NetworkManager-wait-online.service [Service] ExecStart=-/usr/bin/nmcli c up "System $1" Type=oneshot RemainAfterExit=true [Install] WantedBy=default.target EOF mkdir -p /run/systemd/system/default.target.wants ln -sf /run/systemd/system/network-connection-activate.service /run/systemd/system/default.target.wants/network-connection-activate.service } # fix_nm_link_state forces the network interface to a DOWN state ahead of NetworkManager starting up fix_nm_link_state() { [ -e "/sys/class/net/$1" ] || return 0 ip_path= if [ -f /sbin/ip ]; then ip_path=/sbin/ip elif [ -f /bin/ip ]; then ip_path=/bin/ip else return 0 fi cat <<-EOF > /run/systemd/system/network-device-down.service [Unit] Description=Turn off network device Before=NetworkManager.service [Service] ExecStart=-${ip_path} link set $1 down Type=oneshot RemainAfterExit=true [Install] WantedBy=default.target EOF mkdir -p /run/systemd/system/default.target.wants ln -sf /run/systemd/system/network-device-down.service /run/systemd/system/default.target.wants/network-device-down.service } # fix_systemd_override_unit generates a unit specific override fix_systemd_override_unit() { dropin_dir="/run/systemd/${1}.d" mkdir -p "${dropin_dir}" echo "[Service]" > "${dropin_dir}/zzz-lxc-service.conf" [ "${systemd_version}" -ge 247 ] && echo "ProtectProc=default" >> "${dropin_dir}/zzz-lxc-service.conf" [ "${systemd_version}" -ge 232 ] && echo "ProtectControlGroups=no" >> "${dropin_dir}/zzz-lxc-service.conf" [ "${systemd_version}" -ge 232 ] && echo "ProtectKernelTunables=no" >> "${dropin_dir}/zzz-lxc-service.conf" # Additional settings for privileged containers if grep -q 4294967295 /proc/self/uid_map; then echo "ProtectHome=no" >> "${dropin_dir}/zzz-lxc-service.conf" echo "ProtectSystem=no" >> "${dropin_dir}/zzz-lxc-service.conf" echo "PrivateDevices=no" >> "${dropin_dir}/zzz-lxc-service.conf" echo "PrivateTmp=no" >> "${dropin_dir}/zzz-lxc-service.conf" [ "${systemd_version}" -ge 244 ] && echo "ProtectKernelLogs=no" >> "${dropin_dir}/zzz-lxc-service.conf" [ "${systemd_version}" -ge 232 ] && echo "ProtectKernelModules=no" >> "${dropin_dir}/zzz-lxc-service.conf" echo "ReadWritePaths=" >> "${dropin_dir}/zzz-lxc-service.conf" fi } # fix_systemd_mask masks the systemd unit fix_systemd_mask() { ln -sf /dev/null /run/systemd/system/$1 } # fix_systemd_udev_trigger overrides the systemd-udev-trigger.service to match the latest version # of the file which uses "ExecStart=-" instead of "ExecStart=". fix_systemd_udev_trigger() { mkdir -p /run/systemd/system/systemd-udev-trigger.service.d cat <<-EOF > /run/systemd/system/systemd-udev-trigger.service.d/zzz-lxc-override.conf [Service] ExecStart= ExecStart=-udevadm trigger --type=subsystems --action=add ExecStart=-udevadm trigger --type=devices --action=add EOF } # fix_systemd_sysctl overrides the systemd-sysctl.service to use "ExecStart=-" instead of "ExecStart=". fix_systemd_sysctl() { mkdir -p /run/systemd/system/systemd-sysctl.service.d cat <<-EOF > /run/systemd/system/systemd-sysctl.service.d/zzz-lxc-override.conf [Service] ExecStart= ExecStart=-/usr/lib/systemd/systemd-sysctl EOF } ## Main logic # Exit immediately if not a LXC/LXD container or VM if ! is_lxd_vm && ! is_lxc_container; then exit fi # Check for NetworkManager and cloud-init nm_exists=0 cloudinit_exists=0 is_in_path NetworkManager && nm_exists=1 is_in_path cloud-init && cloudinit_exists=1 # Determine systemd version for path in /usr/lib/systemd/systemd /lib/systemd/systemd; do [ -x "${path}" ] || continue systemd_version="$("${path}" --version | head -n1 | cut -d' ' -f2)" break done # Determine distro name and release ID="" VERSION_ID="" if [ -e /etc/os-release ]; then . /etc/os-release fi # Apply systemd overrides if [ "${systemd_version}" -ge 244 ]; then fix_systemd_override_unit system/service else # Setup per-unit overrides find /lib/systemd /etc/systemd /run/systemd /usr/lib/systemd -name "*.service" -type f | sed 's#/\(lib\|etc\|run\|usr/lib\)/systemd/##g'| while read -r service_file; do fix_systemd_override_unit "${service_file}" done fi # Workarounds for all containers if is_lxc_container; then fix_systemd_udev_trigger fix_systemd_sysctl fix_systemd_mask dev-hugepages.mount fix_systemd_mask systemd-journald-audit.socket fix_systemd_mask run-ribchester-general.mount fix_systemd_mask systemd-modules-load.service fix_systemd_mask systemd-pstore.service fix_systemd_mask ua-messaging.service if [ ! -e /dev/tty1 ]; then fix_systemd_mask vconsole-setup-kludge@tty1.service fi if ! grep -q 4294967295 /proc/self/uid_map && { [ "${ID}" = "altlinux" ] || [ "${ID}" = "arch" ] || [ "${ID}" = "fedora" ]; }; then fix_ro_paths systemd-networkd.service fix_ro_paths systemd_resolved.servce fi fi # Workarounds for cloud containers if is_lxc_container && { [ "${ID}" = "fedora" ] || [ "${ID}" = "rhel" ]; } && [ "${cloudinit_exists}" -eq 1 ]; then fix_nm_force_up eth0 fi # Workarounds for NetworkManager in containers if [ "${nm_exists}" -eq 1 ]; then if [ "${ID}" = "ol" ] || [ "${ID}" = "centos" ]; then fix_nm_force_up eth0 fi fix_nm_link_state eth0 fi @@@ chmod 755 "$generators_dir"/lxc