You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
226 lines
6.7 KiB
226 lines
6.7 KiB
3 years ago
|
#!/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
|