initial commit for base kind

This commit is contained in:
fl0pp5 2024-11-14 09:15:46 +03:00
commit deb1cacb01
79 changed files with 2431 additions and 0 deletions

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# altcos-config
ALT Container OS configuration files

15
config.mk Normal file
View File

@ -0,0 +1,15 @@
ifeq (vm,$(IMAGE_CLASS))
use/altcos: vm/.base-grub use/datetime use/docs/license use/init/systemd use/net-eth/networkd-dhcp use/net-ssh use/deflogin
@$(call add_feature)
@$(call add,BASE_PACKAGES,ostree ignition zincati libnss-altfiles) # ostree core
@$(call add,BASE_PACKAGES,sudo su rng-tools systemd-networkd jq policycoreutils bsdtar cloud-utils-growpart fdisk sfdisk) # required utils
@$(call add,BASE_PACKAGES,podman docker-engine docker-compose-v2) # container utils
@$(call add,BASE_PACKAGES,schilytools vim bash-completion fonts-console-spleen fonts-console-terminus glibc-locales) # handy tools
@$(call add,DEFAULT_SERVICES_ENABLE,ostree-remount zincati sshd systemd-resolved coreos-ignition-firstboot-complete)
@$(call set,TARGET_HOSTNAME,altcos)
@$(call xport,CINCINNATI_URL)
@$(call set,CINCINNATI_URL,https://altcos.altlinux.org)
@$(call xport,BRANCH,$(BRANCH))
@$(call xport,ARCH,$(ARCH))
@$(call set,TIME_UTC,0)
endif

6
rootfs/files/etc/issue Normal file
View File

@ -0,0 +1,6 @@
\e[33;40;1m* ALT Container OS *\e[0m
date: \t \d
eth0: \4{eth0}
admin: alt

View File

@ -0,0 +1 @@
LANG="C.UTF-8"

View File

@ -0,0 +1,3 @@
# We don't ship cracklib dicts, so don't try to use them to validate
# password changes.
dictcheck = 0

View File

@ -0,0 +1 @@
%wheel ALL=(ALL) NOPASSWD: ALL

View File

@ -0,0 +1 @@
zincati ALL=NOPASSWD: ALL

View File

@ -0,0 +1,5 @@
[Match]
Name=eth0
[Network]
DHCP=yes

View File

@ -0,0 +1,2 @@
FONT=default8x16
FONT_UNIMAP=cyralt

View File

@ -0,0 +1,30 @@
# File intended to be sourced by shell script generators shipped with CoreOS systems
# Generators don't have logging right now
# https://github.com/systemd/systemd/issues/15638
exec 1>/dev/kmsg; exec 2>&1
UNIT_DIR="${1:-/tmp}"
have_karg() {
local arg="$1"
IFS=" " read -r -a cmdline <<< "$(</proc/cmdline)"
local i
for i in "${cmdline[@]}"; do
if [[ "$i" =~ "$arg=" ]]; then
return 0
fi
done
return 1
}
karg() {
local name="$1" value="${2:-}"
IFS=" " read -r -a cmdline <<< "$(</proc/cmdline)"
for arg in "${cmdline[@]}"; do
if [[ "${arg%%=*}" == "${name}" ]]; then
value="${arg#*=}"
fi
done
echo "${value}"
}

View File

@ -0,0 +1,2 @@
# Default rpm-ostree model is server-side generated initramfs
hostonly=no

View File

@ -0,0 +1,3 @@
# We don't ship `strip` or `eu-strip` today, and even if we did, it doesn't
# save much space. So let's disable it to avoid the error-looking message.
do_strip=no

View File

@ -0,0 +1,15 @@
# We don't support root on NFS, so we don't need it in the initramfs. It also
# conflicts with /var mount support in ignition because NFS tries to mount stuff
# in /var/ and then ignition can't cleanly unmount it. For example:
# https://github.com/dracutdevs/dracut/blob/1856ae95c873a6fe855b3dccd0144f1a96b9e71c/modules.d/95nfs/nfs-start-rpc.sh#L7
# See also discussion in https://github.com/coreos/fedora-coreos-config/pull/60
# Further, we currently do not use LVM or dmraid
omit_dracutmodules+=" nfs lvm dmraid "
omit_dracutmodules+=" ifcfg "
# We use systemd network naming
omit_dracutmodules+=" biosdevname "
# Random stuff we don't want
omit_dracutmodules+=" dbus-daemon memstrack iscsi "
omit_drivers+=" floppy "

View File

@ -0,0 +1,4 @@
# Compress initrd with zstd. dracut defaults to -15, but we want the
# maximum reasonable compression, so override the command line to use
# dracut's defaults along with -19.
compress="zstd -19 -q -T0"

View File

@ -0,0 +1,15 @@
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
# Note from ALT Linux's dudes: isci is not tested now and this file just for compability
# 1) Fix for https://bugzilla.redhat.com/show_bug.cgi?id=1918244
# On s390x systems with IBM 2810XIV discs multipath couldn't be configured
# because SCSI_IDENT_* udev properties are not set at boot time
# 2-) Fix for https://bugzilla.redhat.com/show_bug.cgi?id=1990506
# Missing symlinks to disk install
install() {
inst_simple sg_inq
inst_rules 55-scsi-sg3_id
inst_rules 58-scsi-sg3_symlink
}

View File

@ -0,0 +1,23 @@
# For now we are using kmsg [1] for multiplexing output to
# multiple console devices during early boot. We need to also tell
# the kernel not to ratelimit kmsg during the initramfs.
#
# We do not want to use kmsg in the future as there may be sensitive
# ignition data that leaks to non-root users (by reading the kernel
# ring buffer using `dmesg`). In the future we will rely on kernel
# console multiplexing [2] for this and will not use kmsg.
#
# [1] https://github.com/coreos/ignition-dracut/blob/26f2396b116286dcb46644dc157e4211aea3aba5/dracut/99journald-conf/00-journal-log-forwarding.conf#L2
# [2] https://github.com/coreos/fedora-coreos-tracker/issues/136
# See also 10-coreos-ratelimit-kmsg.conf, which turns ratelimiting back *on*
# in the real root.
check() {
return 0
}
install() {
mkdir -p "$initdir/etc/sysctl.d"
echo "kernel.printk_devkmsg = on" > "$initdir/etc/sysctl.d/10-dont-ratelimit-kmsg.conf"
}

View File

@ -0,0 +1,18 @@
{
"ignition": {
"version": "3.0.0"
},
"passwd": {
"users": [
{
"name": "alt",
"gecos": "ALT Container OS admin",
"groups": [
"adm",
"wheel",
"systemd-journal"
]
}
]
}
}

View File

@ -0,0 +1,13 @@
#!/bin/bash
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
depends() {
echo ignition
}
install() {
mkdir -p "$initdir/usr/lib/ignition/base.d"
inst "$moddir/00-core.ign" \
"/usr/lib/ignition/base.d/00-core.ign"
}

View File

@ -0,0 +1,37 @@
#!/bin/bash
set -euo pipefail
# See also ignition-ostree-check-rootfs-size.service
# https://github.com/coreos/fedora-coreos-tracker/issues/586#issuecomment-777220000
# /sysroot is the mounted deploy root, /sysroot/sysroot is the physical root filesystem
srcdev=$(findmnt -nvr -o SOURCE /sysroot/sysroot | tail -n1)
size=$(lsblk --nodeps --noheadings --bytes -o SIZE "${srcdev}")
MINIMUM_GB=8
MINIMUM_BYTES=$((1024 * 1024 * 1024 * MINIMUM_GB))
MOTD_DROPIN=/etc/motd.d/60-coreos-rootfs-size.motd
YELLOW=$(echo -e '\033[0;33m')
RESET=$(echo -e '\033[0m')
if [ "${size}" -lt "${MINIMUM_BYTES}" ]; then
mkdir -p "/sysroot/$(dirname "${MOTD_DROPIN}")"
cat > "/sysroot/${MOTD_DROPIN}" <<EOF
${YELLOW}
############################################################################
WARNING: The root filesystem is too small. It is strongly recommended to
allocate at least ${MINIMUM_GB} GiB of space to allow for upgrades. From June 2021, this
condition will trigger a failure in some cases. For more information, see:
https://docs.fedoraproject.org/en-US/fedora-coreos/storage/
You may delete this warning using:
sudo rm ${MOTD_DROPIN}
############################################################################
${RESET}
EOF
# And also write it on stdout for the journal and console
cat "/sysroot/${MOTD_DROPIN}"
fi

View File

@ -0,0 +1,37 @@
#!/bin/bash
# From ALT Linux maintainer: this file will be used in future
set -euo pipefail
err() {
echo "$@" >&2
}
fatal() {
err "$@"
exit 1
}
if [ $# -eq 0 ]; then
err "Usage: $0 [PATTERN...]"
err " e.g.: $0 /etc/passwd '/etc/group*'"
fi
if [ ! -f /sysroot/etc/selinux/config ]; then
exit 0
fi
source /sysroot/etc/selinux/config
if [ -z "${SELINUXTYPE:-}" ]; then
fatal "Couldn't find SELINUXTYPE in /sysroot/etc/selinux/config"
fi
file_contexts="/sysroot/etc/selinux/${SELINUXTYPE}/contexts/files/file_contexts"
prefixed_patterns=()
while [ $# -ne 0 ]; do
pattern=$1; shift
prefixed_patterns+=("/sysroot/$pattern")
done
setfiles -vFi0 -r /sysroot "$file_contexts" "${prefixed_patterns[@]}"

View File

@ -0,0 +1,16 @@
[Unit]
Description=Ignition OSTree: Check Root Filesystem Size
Documentation=https://docs.fedoraproject.org/en-US/fedora-coreos/storage/
DefaultDependencies=false
ConditionKernelCommandLine=ostree
ConditionPathExists=!/run/ostree-live
After=ignition-ostree-growfs.service
After=ostree-prepare-root.service
Requires=ostree-prepare-root.service
# Allow Ignition config to blank out the warning
Before=ignition-files.service
[Service]
Type=oneshot
ExecStart=/usr/libexec/coreos-check-rootfs-size
RemainAfterExit=yes

View File

@ -0,0 +1,38 @@
#!/bin/bash
set -euo pipefail
# https://github.com/coreos/fedora-coreos-tracker/issues/465
# coreos-assembler generates disk images which are installed bit-for-bit
# or booted directly in the cloud.
# Generate new UUID on firstboot; this is general best practice, but in the future
# we may use this for mounting by e.g. adding a boot=<uuid> and root=<uuid> kernel args.
label=$1
# Keep this in sync with https://github.com/coreos/coreos-assembler/blob/e3905fd2e138de04184c1cd86b99b0fd83cbe5cf/src/create_disk.sh#L17
bootfs_uuid="96d15588-3596-4b3c-adca-a2ff7279ea63"
rootfs_uuid="910678ff-f77e-4a7d-8d53-86f2ac47a823"
target=/dev/disk/by-label/${label}
if ! [ -b "${target}" ]; then
echo "$0: Failed to find block device ${target}" 1>&2
exit 1
fi
eval $(blkid -p -o export ${target})
case "${label}" in
root) orig_uuid="${rootfs_uuid}"; orig_type=xfs ;;
boot) orig_uuid="${bootfs_uuid}"; orig_type=ext4 ;;
*) echo "unexpected ${label}"; exit 1 ;;
esac
if [ "${TYPE}" == "${orig_type}" ] && [ "${UUID}" == "${orig_uuid}" ]; then
case "${TYPE}" in
ext4) tune2fs -U random "${target}" ;;
xfs) xfs_admin -U generate "${target}" ;;
*) echo "unexpected filesystem type ${TYPE}" 1>&2; exit 1 ;;
esac
udevadm settle || :
echo "Regenerated UUID for ${target}"
else
echo "No changes required for ${target} TYPE=${TYPE} UUID=${UUID}"
fi

View File

@ -0,0 +1,15 @@
[Unit]
Description=Ignition OSTree: Grow Root Filesystem
DefaultDependencies=false
ConditionKernelCommandLine=ostree
ConditionPathExists=!/run/ostree-live
Before=initrd-root-fs.target
Before=sysroot.mount
After=ignition-ostree-uuid-root.service
[Service]
Type=oneshot
ExecStart=/usr/sbin/ignition-ostree-growfs
RemainAfterExit=yes
# So we can transiently mount sysroot
MountFlags=slave

View File

@ -0,0 +1,178 @@
#!/bin/bash
set -euo pipefail
# This script is run by ignition-ostree-growfs.service. It grows the root
# partition, unless it determines that either the rootfs was moved or the
# partition was already resized (e.g. via Ignition).
# In the IBM Secure Execution case we use Ignition to grow and reencrypt rootfs
# see overlay.d/05core/usr/lib/dracut/modules.d/35coreos-ignition/coreos-diskful-generator
if [[ -f /run/coreos/secure-execution ]]; then
exit 0
fi
# This is copied from ignition-ostree-transposefs.sh.
# Sometimes, for some reason the by-label symlinks aren't updated. Detect these
# cases, and explicitly `udevadm trigger`.
# See: https://bugzilla.redhat.com/show_bug.cgi?id=1908780
udev_trigger_on_label_mismatch() {
local label=$1; shift
local expected_dev=$1; shift
local actual_dev
expected_dev=$(realpath "${expected_dev}")
# We `|| :` here because sometimes /dev/disk/by-label/$label is missing.
# We've seen this on Fedora kernels with debug enabled (common in `rawhide`).
# See https://github.com/coreos/fedora-coreos-tracker/issues/1092
actual_dev=$(realpath "/dev/disk/by-label/$label" || :)
if [ "$actual_dev" != "$expected_dev" ]; then
echo "Expected /dev/disk/by-label/$label to point to $expected_dev, but points to $actual_dev; triggering udev"
udevadm trigger --settle "$expected_dev"
fi
}
# This is also similar to bits from transposefs.sh.
ignition_cfg=/run/ignition.json
expected_dev=$(jq -r '.storage?.filesystems? // [] | map(select(.label == "root")) | .[0].device // ""' "${ignition_cfg}")
if [ -n "${expected_dev}" ]; then
udev_trigger_on_label_mismatch root "${expected_dev}"
fi
# If root reprovisioning was triggered, this file contains state of the root
# partition *before* ignition-disks.
saved_partstate=/run/ignition-ostree-rootfs-partstate.sh
# We run before the rootfs is mounted at /sysroot, but we still need to mount it
# (in a private namespace) since XFS and Btrfs can only do resizing online (EXT4
# can do either).
path=/sysroot
src=/dev/disk/by-label/root
mount "${src}" "${path}"
if [ ! -f "${saved_partstate}" ]; then
partition=$(realpath /dev/disk/by-label/root)
else
# The rootfs was reprovisioned. Our rule in this case is: we only grow if
# the partition backing the rootfs is the same and its size didn't change
# (IOW, it was an in-place reprovisioning; e.g. LUKS or xfs -> btrfs).
source "${saved_partstate}"
if [ "${TYPE}" != "part" ]; then
# this really should never happen; but play nice
echo "$0: original rootfs blockdev not of type 'part'; not auto-growing"
exit 0
fi
partition=$(realpath "${NAME}")
if [ "${SIZE}" != "$(lsblk --nodeps -bno SIZE "${partition}")" ]; then
echo "$0: original root partition changed size; not auto-growing"
exit 0
fi
if ! lsblk -no MOUNTPOINT "${partition}" | grep -q '^/sysroot$'; then
echo "$0: original root partition no longer backing rootfs; not auto-growing"
exit 0
fi
fi
# Go through each blockdev in the hierarchy and verify we know how to grow them
lsblk -no TYPE "${partition}" | while read dev; do
case "${dev}" in
part|crypt) ;;
*) echo "error: Unsupported blockdev type ${dev}" 1>&2; exit 1 ;;
esac
done
# Get the filesystem type before extending the partition. This matters
# because the partition, once extended, might include leftover superblocks
# from the previous contents of the disk (notably ZFS), causing blkid to
# refuse to return any filesystem type at all.
eval $(blkid -p -o export "${src}")
ROOTFS_TYPE=${TYPE:-}
case "${ROOTFS_TYPE}" in
xfs|ext4|btrfs) ;;
*) echo "error: Unsupported filesystem for ${path}: '${ROOTFS_TYPE}'" 1>&2; exit 1 ;;
esac
# Now, go through the hierarchy, growing everything. Note we go one device at a
# time using --nodeps, because ordering is buggy in el8:
# https://bugzilla.redhat.com/show_bug.cgi?id=1940607
current_blkdev=${partition}
while true; do
eval "$(lsblk --paths --nodeps --pairs -o NAME,TYPE,PKNAME "${current_blkdev}")"
MAJMIN=$(echo $(lsblk -dno MAJ:MIN "${NAME}"))
case "${TYPE}" in
part)
eval $(udevadm info --query property --export "${current_blkdev}" | grep ^DM_ || :)
if [ -n "${DM_MPATH:-}" ]; then
PKNAME=/dev/mapper/${DM_MPATH}
partnum=${DM_PART}
# Since growpart does not understand device mapper, we have to use sfdisk.
echo ", +" | sfdisk --no-reread --no-tell-kernel --force -N "${partnum}" "${PKNAME}"
udevadm settle || : # Wait for udev-triggered kpartx to update mappings
elif [[ "${PKNAME}" = /dev/dasd* ]]; then
echo "partition is on DASD device; skipping growpart"
else
partnum=$(cat "/sys/dev/block/${MAJMIN}/partition")
# XXX: ideally this'd be idempotent and we wouldn't `|| :`
growpart "${PKNAME}" "${partnum}" || :
fi
# If this is a 512e disk, then ensure the partition end is 4K
# aligned to be compatible with LUKS. If it's a 4Kn disk, `size`
# necessarily must be 4K aligned (note the sysfs value is always
# reported in 512b sizes). We should be able to drop this once
# https://github.com/util-linux/util-linux/issues/2140 is fixed.
size=$(cat "/sys/dev/block/${MAJMIN}/size")
phy_sec=$(blockdev --getpbsz "${PKNAME}")
if [ "$((size % 8))" != 0 ] && [ "${phy_sec:-}" = 4096 ]; then
size=$(((size >> 3) << 3)) # round down to nearest 4K boundary
echo ", ${size}" | sfdisk --no-reread --force -N "${partnum}" "${PKNAME}"
partx --update --nr "${partnum}" "${PKNAME}"
fi
;;
crypt)
# lsblk doesn't print PKNAME of crypt devices with --nodeps
PKNAME=/dev/$(ls "/sys/dev/block/${MAJMIN}/slaves")
LUKS_DUMP=$(cryptsetup luksDump "$PKNAME" --dump-json-metadata)
if jq -e '[.tokens[].type] | index("clevis")' <<< "$LUKS_DUMP"; then
# XXX: yuck... we need to expose this sanely in clevis
(. /usr/bin/clevis-luks-common-functions
eval $(udevadm info --query=property --export "${NAME}")
clevis_luks_unlock_device "${PKNAME}" | cryptsetup resize -d- "${DM_NAME}"
)
elif jq -e '.segments["0"].encryption | startswith("paes")' <<< "$LUKS_DUMP"; then
# CEX LUKS volume: https://github.com/coreos/ignition/issues/1693
cryptsetup resize root --key-file /etc/luks/cex.key
else
echo "$LUKS_DUMP"
echo "error: unknown LUKS device"
exit 1
fi
;;
# already checked
*) echo "unreachable" 1>&2; exit 1 ;;
esac
holders="/sys/dev/block/${MAJMIN}/holders"
[ -d "${holders}" ] || break
nholders="$(ls "${holders}" | wc -l)"
if [ "${nholders}" -eq 0 ]; then
break
elif [ "${nholders}" -gt 1 ]; then
# this shouldn't happen since we've checked the partition types already
echo "error: Unsupported block device with multiple children: ${NAME}" 1>&2
exit 1
fi
current_blkdev=/dev/$(ls "${holders}")
done
# Wipe any filesystem signatures from the extended partition that don't
# correspond to the FS type we detected earlier.
wipefs -af -t "no${ROOTFS_TYPE}" "${src}"
# TODO: Add XFS to https://github.com/systemd/systemd/blob/master/src/partition/growfs.c
# and use it instead.
case "${ROOTFS_TYPE}" in
xfs) xfs_growfs "${path}" ;;
ext4) resize2fs "${src}" ;;
btrfs) btrfs filesystem resize max ${path} ;;
esac
# The ignition-ostree-transposefs-xfsauto.service unit needs to know if we
# actually run. This is also useful for tests.
touch /run/ignition-ostree-growfs.stamp

View File

@ -0,0 +1,19 @@
[Unit]
Description=Ignition OSTree Mount State Overlays
DefaultDependencies=false
ConditionKernelCommandLine=|ostree
ConditionPathExists=|/run/ostree-live
# Need to do this with all mount points active
After=ignition-mount.service
# Not strictly required, but both do /var things
After=ignition-ostree-populate-var.service
# But *before* we start dumping files in there
Before=ignition-files.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/libexec/ignition-ostree-mount-state-overlays mount
ExecStop=/usr/libexec/ignition-ostree-mount-state-overlays umount

View File

@ -0,0 +1,50 @@
#!/bin/bash
set -euo pipefail
fatal() {
echo "$@" >&2
exit 1
}
if [ $# -ne 1 ] || { [[ $1 != mount ]] && [[ $1 != umount ]]; }; then
fatal "Usage: $0 <mount|umount>"
fi
# if state overlays are not enabled, there's nothing to do
if ! ls /sysroot/usr/lib/systemd/system/local-fs.target.requires/ostree-state-overlay@*.service 2>/dev/null; then
exit 0
fi
do_mount() {
# be nice to persistent /var; if the top-level state overlay dir exists,
# then assume it's properly labeled
relabel=1
state_overlays_dir=/sysroot/var/ostree/state-overlays
if [ -d ${state_overlays_dir} ]; then
relabel=0
fi
for overlay in /usr/lib/opt /usr/local; do
escaped=$(systemd-escape --path "${overlay}")
overlay_dirs=${state_overlays_dir}/${escaped}
mkdir -p "${overlay_dirs}"/{upper,work}
# ideally we'd use `ostree admin state-overlay`, but that'd require
# pulling in bwrap and chroot which isn't yet in the FCOS initrd
mount -t overlay overlay /sysroot/${overlay} -o "lowerdir=/sysroot/${overlay},upperdir=${overlay_dirs}/upper,workdir=${overlay_dirs}/work"
done
if [ $relabel = 1 ]; then
coreos-relabel /var/ostree
# the above relabel will have relabeled the upperdir too; relabel that
# from the perspective of the mount point so it's not var_t
for overlay in /usr/lib/opt /usr/local; do
coreos-relabel ${overlay}
done
fi
}
do_umount() {
for overlay in /usr/lib/opt /usr/local; do
umount /sysroot/${overlay}
done
}
"do_$1"

View File

@ -0,0 +1,26 @@
[Unit]
Description=Mount OSTree /var
DefaultDependencies=false
ConditionKernelCommandLine=ostree
ConditionPathExists=!/run/ostree-live
# Make sure ExecStop= runs before we switch root
Before=initrd-switch-root.target
# Make sure if ExecStop= fails, the boot fails
OnFailure=emergency.target
OnFailureJobMode=isolate
# Make sure /sysroot is mounted first, since we're mounting under there
Requires=initrd-root-fs.target
After=initrd-root-fs.target
# Need to do this before Ignition mounts any other filesystems (potentially
# shadowing our own bind mount).
Before=ignition-mount.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/ignition-ostree-mount-var mount
ExecStop=/usr/sbin/ignition-ostree-mount-var umount

View File

@ -0,0 +1,52 @@
#!/bin/bash
set -euo pipefail
fatal() {
echo "$@" >&2
exit 1
}
if [ $# -ne 1 ] || { [[ $1 != mount ]] && [[ $1 != umount ]]; }; then
fatal "Usage: $0 <mount|umount>"
fi
get_ostree_arg() {
# yes, this doesn't account for spaces within args, e.g. myarg="my val", but
# it still works for our purposes
(
IFS=$' '
# shellcheck disable=SC2013
for arg in $(cat /proc/cmdline); do
if [[ $arg == ostree=* ]]; then
echo "${arg#ostree=}"
fi
done
)
}
do_mount() {
ostree=$(get_ostree_arg)
if [ -z "${ostree}" ]; then
fatal "No ostree= kernel argument in /proc/cmdline"
fi
deployment_path=/sysroot/${ostree}
if [ ! -L "${deployment_path}" ]; then
fatal "${deployment_path} is not a symlink"
fi
stateroot_var_path=$(realpath "${deployment_path}/../../var")
if [ ! -d "${stateroot_var_path}" ]; then
fatal "${stateroot_var_path} is not a directory"
fi
echo "Mounting $stateroot_var_path"
mount --bind "$stateroot_var_path" /sysroot/var
}
do_umount() {
echo "Unmounting /sysroot/var"
umount /sysroot/var
}
"do_$1"

View File

@ -0,0 +1,16 @@
[Unit]
Description=Populate OSTree /var
DefaultDependencies=false
ConditionKernelCommandLine=|ostree
ConditionPathExists=|/run/ostree-live
# Need to do this with all mount points active
After=ignition-mount.service
# But *before* we start dumping files in there
Before=ignition-files.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/ignition-ostree-populate-var

View File

@ -0,0 +1,42 @@
#!/bin/bash
set -euo pipefail
fatal() {
echo "$@" >&2
exit 1
}
if [ $# -ne 0 ]; then
fatal "Usage: $0"
fi
# See the similar code block in Anaconda, which handles this today for Atomic
# Host and Silverblue:
# https://github.com/rhinstaller/anaconda/blob/b9ea8ce4e68196b30a524c1cc5680dcdc4b89371/pyanaconda/payload/rpmostreepayload.py#L332
for varsubdir in lib log home roothome opt srv usrlocal mnt media; do
# If the directory already existed, just ignore. This addresses the live
# image case with persistent `/var`; we don't want to relabel all the files
# there on each boot.
if [ -d "/sysroot/var/${varsubdir}" ]; then
continue
fi
if [[ $varsubdir == lib ]] || [[ $varsubdir == log ]]; then
# Simply manually mkdir /var/{lib,log}; the tmpfiles.d entries otherwise
# reference users/groups which we don't have access to from here
# (though... we *could* import them from the sysroot, and have
# nss-altfiles in the initrd, but meh... let's just wait for
# systemd-sysusers which will make this way easier:
# https://github.com/coreos/fedora-coreos-config/pull/56/files#r262592361).
mkdir -p /sysroot/var/${varsubdir}
else
systemd-tmpfiles --create --boot --root=/sysroot --prefix="/var/${varsubdir}"
fi
coreos-relabel "/var/${varsubdir}"
done
# mount /proc dir for the properly user creation (if not mounted SKEL is broken)
mount --bind /proc /sysroot/proc

View File

@ -0,0 +1,23 @@
[Unit]
Description=Ignition OSTree: Autosave XFS Rootfs Partition
DefaultDependencies=false
After=ignition-disks.service
# Avoid racing with UUID regeneration
After=ignition-ostree-uuid-root.service
After=ignition-ostree-growfs.service
# https://issues.redhat.com/browse/OCPBUGS-16157
# On multipath systems mounting the /sysroot before
# the ignition-ostree services causes the transpose to fail.
Before=sysroot.mount
Before=ignition-ostree-transposefs-restore.service
OnFailure=emergency.target
OnFailureJobMode=isolate
ConditionKernelCommandLine=ostree
# only run if ignition-ostree-growfs ran since that's when pathological cases occur
ConditionPathExists=/run/ignition-ostree-growfs.stamp
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/libexec/ignition-ostree-transposefs autosave-xfs

View File

@ -0,0 +1,20 @@
[Unit]
Description=Ignition OSTree: Detect Partition Transposition
DefaultDependencies=false
After=ignition-fetch.service
Before=ignition-disks.service
Before=initrd-root-fs.target
Before=sysroot.mount
ConditionKernelCommandLine=ostree
OnFailure=emergency.target
OnFailureJobMode=isolate
# This stage requires udevd to detect disks
Requires=systemd-udevd.service
After=systemd-udevd.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/libexec/ignition-ostree-transposefs detect
ExecStop=/usr/libexec/ignition-ostree-transposefs cleanup

View File

@ -0,0 +1,23 @@
[Unit]
Description=Ignition OSTree: Restore Partitions
DefaultDependencies=false
After=ignition-disks.service
# Avoid racing with UUID regeneration
After=ignition-ostree-uuid-root.service
After=ignition-ostree-growfs.service
# https://issues.redhat.com/browse/OCPBUGS-16157
# On multipath systems mounting the /sysroot before
# the ignition-ostree services causes the transpose to fail.
Before=sysroot.mount
OnFailure=emergency.target
OnFailureJobMode=isolate
ConditionKernelCommandLine=ostree
ConditionPathIsDirectory=/run/ignition-ostree-transposefs
[Service]
Type=oneshot
RemainAfterExit=yes
# So we can transiently mount sysroot
MountFlags=slave
ExecStart=/usr/libexec/ignition-ostree-transposefs restore

View File

@ -0,0 +1,19 @@
[Unit]
Description=Ignition OSTree: Save Partitions
DefaultDependencies=false
After=ignition-ostree-transposefs-detect.service
Before=ignition-disks.service
ConditionKernelCommandLine=ostree
ConditionPathIsDirectory=/run/ignition-ostree-transposefs
# Any services looking at mounts need to order after this
# because it causes device re-probing.
After=coreos-gpt-setup.service
OnFailure=emergency.target
OnFailureJobMode=isolate
[Service]
Type=oneshot
RemainAfterExit=yes
# So we can transiently mount sysroot
MountFlags=slave
ExecStart=/usr/libexec/ignition-ostree-transposefs save

View File

@ -0,0 +1,388 @@
#!/bin/bash
set -euo pipefail
boot_sector_size=440
esp_typeguid=c12a7328-f81f-11d2-ba4b-00a0c93ec93b
bios_typeguid=21686148-6449-6e6f-744e-656564454649
prep_typeguid=9e1a2d38-c612-4316-aa26-8b49521e5a8b
# This is implementation details of Ignition; in the future, we should figure
# out a way to ask Ignition directly whether there's a filesystem with label
# "root" being set up.
ignition_cfg=/run/ignition.json
root_part=/dev/disk/by-label/root
boot_part=/dev/disk/by-label/boot
esp_part=/dev/disk/by-label/EFI-SYSTEM
bios_part=/dev/disk/by-partlabel/BIOS-BOOT
prep_part=/dev/disk/by-partlabel/PowerPC-PReP-boot
saved_data=/run/ignition-ostree-transposefs
saved_root=${saved_data}/root
saved_boot=${saved_data}/boot
saved_esp=${saved_data}/esp
saved_bios=${saved_data}/bios
saved_prep=${saved_data}/prep
zram_dev=${saved_data}/zram_dev
partstate_root=/run/ignition-ostree-rootfs-partstate.sh
is_rhcos9() {
source /etc/os-release
[ "${ID}" == "rhcos" ] && [ "${RHEL_VERSION%%.*}" -eq 9 ]
}
# Print jq query string for wiped filesystems with label $1
query_fslabel() {
echo ".storage?.filesystems? // [] | map(select(.label == \"$1\" and .wipeFilesystem == true))"
}
# Print jq query string for partitions with type GUID $1
query_parttype() {
echo ".storage?.disks? // [] | map(.partitions?) | flatten | map(select(has(\"typeGuid\") and (.typeGuid | ascii_downcase == \"$1\")))"
}
# Print partition labels for partitions with type GUID $1
get_partlabels_for_parttype() {
jq -r "$(query_parttype $1) | .[].label" "${ignition_cfg}"
}
# Mounts device to directory, with extra logging of the src device
mount_verbose() {
local srcdev=$1; shift
local destdir=$1; shift
local mode=${1:-ro}
echo "Mounting ${srcdev} ${mode} ($(realpath "$srcdev")) to $destdir"
mkdir -p "${destdir}"
mount -o "${mode}" "${srcdev}" "${destdir}"
}
# A copy of this exists in ignition-ostree-growfs.sh.
# Sometimes, for some reason the by-label symlinks aren't updated. Detect these
# cases, and explicitly `udevadm trigger`.
# See: https://bugzilla.redhat.com/show_bug.cgi?id=1908780
udev_trigger_on_label_mismatch() {
local label=$1; shift
local expected_dev=$1; shift
local actual_dev
expected_dev=$(realpath "${expected_dev}")
# We `|| :` here because sometimes /dev/disk/by-label/$label is missing.
# We've seen this on Fedora kernels with debug enabled (common in `rawhide`).
# See https://github.com/coreos/fedora-coreos-tracker/issues/1092
actual_dev=$(realpath "/dev/disk/by-label/$label" || :)
if [ "$actual_dev" != "$expected_dev" ]; then
echo "Expected /dev/disk/by-label/$label to point to $expected_dev, but points to $actual_dev; triggering udev"
udevadm trigger --settle "$expected_dev"
fi
}
# Print partition offset for device node $1
get_partition_offset() {
local devpath=$(udevadm info --query=path "$1")
cat "/sys${devpath}/start"
}
# copied from generator-lib.sh
karg() {
local name="$1" value="${2:-}"
local cmdline=( $(</proc/cmdline) )
for arg in "${cmdline[@]}"; do
if [[ "${arg%%=*}" == "${name}" ]]; then
value="${arg#*=}"
fi
done
echo "${value}"
}
mount_and_restore_filesystem_by_label() {
local label=$1; shift
local mountpoint=$1; shift
local saved_fs=$1; shift
local new_dev
new_dev=$(jq -r "$(query_fslabel "${label}") | .[0].device // \"\"" "${ignition_cfg}")
# in the autosave-xfs path, it's not driven by the Ignition config so we
# don't expect a new device there
if [ -n "${new_dev}" ]; then
udev_trigger_on_label_mismatch "${label}" "${new_dev}"
fi
mount_verbose "/dev/disk/by-label/${label}" "${mountpoint}" rw
find "${saved_fs}" -mindepth 1 -maxdepth 1 -exec mv -t "${mountpoint}" {} +
}
mount_and_save_filesystem_by_label() {
local label=$1; shift
local saved_fs=$1; shift
local fs=/dev/disk/by-label/${label}
if [[ -f /run/coreos/secure-execution ]]; then
local roothash_karg=${label}fs.roothash
local roothash=$(karg "${roothash_karg}")
if [ -z "${roothash}" ]; then
echo "Missing kernel argument ${roothash_karg}; aborting"
exit 1
fi
local roothash_part=/dev/disk/by-partlabel/${label}hash
veritysetup open "${fs}" "${label}" "${roothash_part}" "${roothash}"
fs=/dev/mapper/${label}
fi
mount_verbose "${fs}" /var/tmp/mnt
cp -aT /var/tmp/mnt "${saved_fs}"
umount /var/tmp/mnt
if [[ -f /run/coreos/secure-execution ]]; then
veritysetup close "${label}"
fi
}
# This implements https://github.com/coreos/fedora-coreos-tracker/issues/1183.
should_autosave_rootfs() {
local fstype
fstype=$(lsblk -no FSTYPE "${root_part}")
if [ "$fstype" != xfs ]; then
echo "Filesystem is not XFS (found $fstype); skipping" >&2
echo 0
return
fi
local agcount
# This runs xfs_info on the unmounted filesystem, because mounting an
# XFS filesystem that has grown an excessive number of allocation groups
# can be very slow.
eval $(xfs_info "${root_part}" | grep -o 'agcount=[0-9]*')
# This is roughly ~700GiB currently (based on initial ag sizing at build time)
# which ensures we grow only on "large" root filesystems.
# Specifically for e.g. OpenShift, this ensures we don't reprovision on default
# worker node root filesystems.
local threshold
threshold=400
if [ "$agcount" -lt "${threshold}" ]; then
echo "autosave-xfs: ${root_part} agcount=$agcount is lower than threshold=${threshold}" >&2
echo 0
return
else
echo "autosave-xfs: ${root_part} agcount=$agcount meets threshold=${threshold}" >&2
echo 1
fi
}
ensure_zram_dev() {
if test -d "${saved_data}"; then
return 0
fi
mem_available=$(grep MemAvailable /proc/meminfo | awk '{print $2}')
# Just error out early if we don't even have 1G to work with. This
# commonly happens if you `cosa run` but forget to add `--memory`. That
# way you get a nicer error instead of the spew of EIO errors from `cp`.
# The amount we need is really dependent on a bunch of factors, but just
# ballpark it at 3G.
if [ "${mem_available}" -lt $((1*1024*1024)) ] && [ "${wipes_root}" != 0 ]; then
echo "Root reprovisioning requires at least 3G of RAM" >&2
exit 1
fi
modprobe zram num_devices=0
read dev < /sys/class/zram-control/hot_add
# disksize is set arbitrarily large, as zram is capped by mem_limit
echo 10G > /sys/block/zram"${dev}"/disksize
# Limit zram to 90% of available RAM: we want to be greedy since the
# boot breaks anyway, but we still want to leave room for everything
# else so it hits ENOSPC and doesn't invoke the OOM killer
echo $(( mem_available * 90 / 100 ))K > /sys/block/zram"${dev}"/mem_limit
mkfs.xfs -q /dev/zram"${dev}"
mkdir "${saved_data}"
mount -t xfs /dev/zram"${dev}" "${saved_data}"
# save the zram device number created for when called to cleanup
echo "${dev}" > "${zram_dev}"
}
print_zram_mm_stat() {
echo "zram usage:"
read dev < "${zram_dev}"
cat /sys/block/zram"${dev}"/mm_stat
}
# In Secure Execution case user is not allowed to modify partition table
check_and_set_secex_config() {
if [[ -f /run/coreos/secure-execution ]]; then
local wr=$(jq "$(query_fslabel root) | length" "${ignition_cfg}")
local wb=$(jq "$(query_fslabel boot) | length" "${ignition_cfg}")
if [ "${wr}${wb}" != "00" ]; then
echo "Modifying bootfs and rootfs is not supported in Secure Execution mode"
exit 1
fi
# Cached config isn't merged, so reset it and recheck again, just to make sure
ignition_cfg=/usr/lib/ignition/base.d/01-secex.ign
fi
}
# We could have done this during 'detect' below, but other cases also request
# info from config, so just check cached one and reset to secex.ign now
check_and_set_secex_config
case "${1:-}" in
detect)
# Mounts are not in a private namespace so we can mount ${saved_data}
wipes_root=$(jq "$(query_fslabel root) | length" "${ignition_cfg}")
wipes_boot=$(jq "$(query_fslabel boot) | length" "${ignition_cfg}")
creates_esp=$(jq "$(query_parttype ${esp_typeguid}) | length" "${ignition_cfg}")
creates_bios=$(jq "$(query_parttype ${bios_typeguid}) | length" "${ignition_cfg}")
creates_prep=$(jq "$(query_parttype ${prep_typeguid}) | length" "${ignition_cfg}")
if [ "${wipes_root}${wipes_boot}${creates_esp}${creates_bios}${creates_prep}" = "00000" ]; then
exit 0
fi
echo "Detected partition replacement in fetched Ignition config: /run/ignition.json"
# verify all ESP, BIOS, and PReP partitions have non-null unique labels
unique_esp=$(jq -r "$(query_parttype ${esp_typeguid}) | [.[].label | values] | unique | length" "${ignition_cfg}")
unique_bios=$(jq -r "$(query_parttype ${bios_typeguid}) | [.[].label | values] | unique | length" "${ignition_cfg}")
unique_prep=$(jq -r "$(query_parttype ${prep_typeguid}) | [.[].label | values] | unique | length" "${ignition_cfg}")
if [ "${creates_esp}" != "${unique_esp}" -o "${creates_bios}" != "${unique_bios}" -o "${creates_prep}" != "${unique_prep}" ]; then
echo "Found duplicate or missing ESP, BIOS-BOOT, or PReP labels in config" >&2
exit 1
fi
ensure_zram_dev
if [ "${wipes_root}" != "0" ]; then
mkdir "${saved_root}"
fi
if [ "${wipes_boot}" != "0" ]; then
mkdir "${saved_boot}"
fi
if [ "${creates_esp}" != "0" ]; then
mkdir "${saved_esp}"
fi
if [ "${creates_bios}" != "0" ]; then
mkdir "${saved_bios}"
fi
if [ "${creates_prep}" != "0" ]; then
mkdir "${saved_prep}"
fi
;;
autosave-xfs)
should_autosave=$(should_autosave_rootfs)
if [ "${should_autosave}" = "1" ]; then
wipes_root=1
ensure_zram_dev
# in the in-place reprovisioning case, the rootfs was already saved
if [ ! -d "${saved_root}" ]; then
mkdir "${saved_root}"
echo "Moving rootfs to RAM..."
mount_and_save_filesystem_by_label root "${saved_root}"
print_zram_mm_stat
fi
mkfs.xfs "${root_part}" -L root -f
# for tests
touch /run/ignition-ostree-autosaved-xfs.stamp
fi
;;
save)
# Mounts happen in a private mount namespace since we're not "offically" mounting
if [ -d "${saved_root}" ]; then
echo "Moving rootfs to RAM..."
mount_and_save_filesystem_by_label root "${saved_root}"
# also store the state of the partition
lsblk "${root_part}" --nodeps --pairs -b --paths -o NAME,TYPE,SIZE > "${partstate_root}"
fi
if [ -d "${saved_boot}" ]; then
echo "Moving bootfs to RAM..."
mount_and_save_filesystem_by_label boot "${saved_boot}"
fi
if [ -d "${saved_esp}" ]; then
echo "Moving EFI System Partition to RAM..."
mount_verbose "${esp_part}" /sysroot/boot/efi
cp -aT /sysroot/boot/efi "${saved_esp}"
fi
if [ -d "${saved_bios}" ]; then
echo "Moving BIOS Boot partition and boot sector to RAM..."
# save partition
cat "${bios_part}" > "${saved_bios}/partition"
# save boot sector
bios_disk=$(lsblk --noheadings --output PKNAME --paths "${bios_part}")
dd if="${bios_disk}" of="${saved_bios}/boot-sector" bs="${boot_sector_size}" count=1 status=none
# store partition start offset so we can check it later
get_partition_offset "${bios_part}" > "${saved_bios}/start"
fi
if [ -d "${saved_prep}" ]; then
echo "Moving PReP partition to RAM..."
cat "${prep_part}" > "${saved_prep}/partition"
fi
print_zram_mm_stat
;;
restore)
# Mounts happen in a private mount namespace since we're not "offically" mounting
if [ -d "${saved_root}" ]; then
echo "Restoring rootfs from RAM..."
mount_and_restore_filesystem_by_label root /sysroot "${saved_root}"
chcon -v --reference "${saved_root}" /sysroot # the root of the fs itself
chattr +i $(ls -d /sysroot/ostree/deploy/*/deploy/*/)
fi
if [ -d "${saved_boot}" ]; then
echo "Restoring bootfs from RAM..."
mount_and_restore_filesystem_by_label boot /sysroot/boot "${saved_boot}"
chcon -v --reference "${saved_boot}" /sysroot/boot # the root of the fs itself
fi
if [ -d "${saved_esp}" ]; then
echo "Restoring EFI System Partition from RAM..."
get_partlabels_for_parttype "${esp_typeguid}" | while read label; do
# Don't use mount_and_restore_filesystem_by_label because:
# 1. We're mounting by partlabel, not FS label
# 2. We need to copy the contents to each partition, not move
# them once
# 3. We don't need the by-label symlink to be correct and
# nothing later in boot will be mounting the filesystem
mountpoint="/mnt/esp-${label}"
mount_verbose "/dev/disk/by-partlabel/${label}" "${mountpoint}" rw
find "${saved_esp}" -mindepth 1 -maxdepth 1 -exec cp -at "${mountpoint}" {} +
done
fi
if [ -d "${saved_bios}" ]; then
echo "Restoring BIOS Boot partition and boot sector from RAM..."
expected_start=$(cat "${saved_bios}/start")
get_partlabels_for_parttype "${bios_typeguid}" | while read label; do
cur_part="/dev/disk/by-partlabel/${label}"
# boot sector hardcodes the partition start; ensure it matches
cur_start=$(get_partition_offset "${cur_part}")
if [ "${cur_start}" != "${expected_start}" ]; then
echo "Partition ${cur_part} starts at ${cur_start}; expected ${expected_start}" >&2
exit 1
fi
# copy partition contents
cat "${saved_bios}/partition" > "${cur_part}"
# copy boot sector
cur_disk=$(lsblk --noheadings --output PKNAME --paths "${cur_part}")
cat "${saved_bios}/boot-sector" > "${cur_disk}"
done
fi
if [ -d "${saved_prep}" ]; then
echo "Restoring PReP partition from RAM..."
get_partlabels_for_parttype "${prep_typeguid}" | while read label; do
cat "${saved_prep}/partition" > "/dev/disk/by-partlabel/${label}"
done
fi
;;
cleanup)
# Mounts are not in a private namespace so we can unmount ${saved_data}
if [ -d "${saved_data}" ]; then
read dev < "${zram_dev}"
umount "${saved_data}"
rm -rf "${saved_data}" "${partstate_root}"
# After unmounting, make sure zram device state is stable before we remove it.
# See https://github.com/openshift/os/issues/1149
# Should remove when https://bugzilla.redhat.com/show_bug.cgi?id=2172058 is fixed.
# Seems the previous workaround https://github.com/coreos/fedora-coreos-config/pull/2226
# can not completely resolve the race issue, try in loop with a small sleep for el9 + !x86_64.
if [ $(uname -m) != x86_64 ] && is_rhcos9; then
for x in {0..10}; do
if ! echo "${dev}" > /sys/class/zram-control/hot_remove 2>/dev/null; then
sleep 0.1
else
dev=
break
fi
done
# try it one last time and let it possibly fail
if [ -n "${dev}" ]; then
echo "${dev}" > /sys/class/zram-control/hot_remove
fi
else
echo "${dev}" > /sys/class/zram-control/hot_remove
fi
fi
;;
*)
echo "Unsupported operation: ${1:-}" 1>&2; exit 1
;;
esac

View File

@ -0,0 +1,24 @@
[Unit]
Description=Ignition OSTree: Regenerate Filesystem UUID (boot)
ConditionPathExists=/usr/lib/initrd-release
ConditionKernelCommandLine=ostree
ConditionPathExists=!/run/ostree-live
# Any services looking at mounts need to order after this
# because it causes device re-probing.
After=coreos-gpt-setup.service
# This could mount the bootfs rw and the ext4 in el9 at least doesn't seem to
# like doing that in parallel with restamping the UUID
Before=ignition-kargs.service
# If we're going to reprovision the bootfs, then there's no need to restamp
ConditionKernelCommandLine=!bootfs.roothash
# uncomment to default
Before=systemd-fsck@dev-disk-by\x2dlabel-boot.service
Requires=dev-disk-by\x2dlabel-boot.device
After=dev-disk-by\x2dlabel-boot.device
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/ignition-ostree-firstboot-uuid boot

View File

@ -0,0 +1,26 @@
[Unit]
Description=Ignition OSTree: Regenerate Filesystem UUID (root)
# These conditions match those generated in coreos-diskful-generator
DefaultDependencies=false
ConditionKernelCommandLine=ostree
ConditionPathExists=!/run/ostree-live
Before=sysroot.mount initrd-root-fs.target
After=ignition-disks.service
# If we've reprovisioned the rootfs, then there's no need to restamp
ConditionPathExists=!/run/ignition-ostree-transposefs
ConditionKernelCommandLine=!rootfs.roothash
After=dev-disk-by\x2dlabel-root.device
# Avoid racing with fsck (uncomment to default)
Before=systemd-fsck@dev-disk-by\x2dlabel-root.service
Before=systemd-fsck@dev-disk-by\x2dlabel-dm-mpath-root.service
# Note we don't have a Requires: /dev/disk/by-label/root here like
# the -subsequent service does because ignition-disks may have
# regenerated it.
Before=sysroot.mount
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/ignition-ostree-firstboot-uuid root

View File

@ -0,0 +1,111 @@
#!/bin/bash
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
depends() {
echo ignition # rdcore
}
install_ignition_unit() {
local unit=$1; shift
local target=${1:-complete}
inst_simple "$moddir/$unit" "$systemdsystemunitdir/$unit"
# note we `|| exit 1` here so we error out if e.g. the units are missing
# see https://github.com/coreos/fedora-coreos-config/issues/799
systemctl -q --root="$initdir" add-requires "ignition-${target}.target" "$unit" || exit 1
}
installkernel() {
# Used by ignition-ostree-transposefs
instmods -c zram
}
install() {
inst_multiple \
realpath \
setfiles \
chcon \
systemd-sysusers \
systemd-tmpfiles \
sort \
xfs_info \
xfs_spaceman \
uniq
if [[ $(uname -m) = s390x ]]; then
# for Secure Execution
inst_multiple \
veritysetup
fi
# ignition-ostree-growfs deps
inst_multiple \
basename \
blkid \
blockdev \
cat \
dirname \
findmnt \
growpart \
realpath \
resize2fs \
tail \
tune2fs \
touch \
xfs_admin \
xfs_growfs \
wc \
wipefs
# growpart deps
# Mostly generated from the following command:
# $ bash --rpm-requires /usr/bin/growpart | sort | uniq | grep executable
# with a few false positives (rq, rqe, -v) and one missed (mktemp)
inst_multiple \
awk \
cat \
dd \
grep \
mktemp \
partx \
rm \
sed \
sfdisk \
sgdisk \
find
for x in mount populate; do
install_ignition_unit ignition-ostree-${x}-var.service
inst_script "$moddir/ignition-ostree-${x}-var.sh" "/usr/sbin/ignition-ostree-${x}-var"
done
inst_simple \
/usr/lib/udev/rules.d/90-coreos-device-mapper.rules
inst_multiple jq chattr
inst_script "$moddir/ignition-ostree-transposefs.sh" "/usr/libexec/ignition-ostree-transposefs"
for x in detect save autosave-xfs restore; do
install_ignition_unit ignition-ostree-transposefs-${x}.service
done
# Disk support
for p in boot root; do
install_ignition_unit ignition-ostree-uuid-${p}.service diskful
done
inst_script "$moddir/ignition-ostree-firstboot-uuid" \
"/usr/sbin/ignition-ostree-firstboot-uuid"
install_ignition_unit ignition-ostree-growfs.service
inst_script "$moddir/ignition-ostree-growfs.sh" \
/usr/sbin/ignition-ostree-growfs
install_ignition_unit ignition-ostree-check-rootfs-size.service
inst_script "$moddir/coreos-check-rootfs-size" \
/usr/libexec/coreos-check-rootfs-size
install_ignition_unit ignition-ostree-mount-state-overlays.service
inst_script "$moddir/ignition-ostree-mount-state-overlays.sh" \
/usr/libexec/ignition-ostree-mount-state-overlays
inst_script "$moddir/coreos-relabel" /usr/bin/coreos-relabel
}

View File

@ -0,0 +1,10 @@
[Unit]
Description=Check That Initrd Matches Kernel
DefaultDependencies=false
Before=sysinit.target systemd-modules-load.service
ConditionPathIsDirectory=!/usr/lib/modules/%v
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/false

View File

@ -0,0 +1,15 @@
install_unit() {
unit="$1"; shift
target="$1"; shift
inst_simple "$moddir/$unit" "$systemdsystemunitdir/$unit"
# note we `|| exit 1` here so we error out if e.g. the units are missing
# see https://github.com/coreos/fedora-coreos-config/issues/799
systemctl -q --root="$initdir" add-requires "$target" "$unit" || exit 1
}
install() {
inst_multiple \
false
install_unit "coreos-check-kernel.service" "sysinit.target"
}

View File

@ -0,0 +1,85 @@
# Display relevant errors then enter emergency shell
# _wait_for_journalctl_to_stop will block until either:
# - no messages have appeared in journalctl for the past 5 seconds
# - 15 seconds have elapsed
_wait_for_journalctl_to_stop() {
local time_since_last_log=0
local time_started="$(date '+%s')"
local now="$(date '+%s')"
while [ ${time_since_last_log} -lt 5 -a $((now-time_started)) -lt 15 ]; do
sleep 1
local last_log_timestamp="$(journalctl -e -n 1 -q -o short-unix | cut -d '.' -f 1)"
local now="$(date '+%s')"
local time_since_last_log=$((now-last_log_timestamp))
done
}
_display_relevant_errors() {
failed=$(systemctl --failed --no-legend --plain | cut -f 1 -d ' ')
if [ -n "${failed}" ]; then
# Something failed, suppress kernel logs so that it's more likely
# the useful bits from the journal are available.
dmesg --console-off
# There's a couple straggler systemd messages. Wait until it's been 5
# seconds since something was written to the journal.
_wait_for_journalctl_to_stop
# Print Ignition logs
if echo ${failed} | grep -qFe 'ignition-'; then
cat <<EOF
------
Ignition has failed. Please ensure your config is valid. Note that only
Ignition spec v3.0.0+ configs are accepted.
A CLI validation tool to check this called ignition-validate can be
downloaded from GitHub:
https://github.com/coreos/ignition/releases
------
EOF
fi
# If this is a live boot, check for ENOSPC in initramfs filesystem
# Try creating a 64 KiB file, in case a small file was deleted on
# service failure
# https://github.com/coreos/fedora-coreos-tracker/issues/1055
if [ -f /etc/coreos-live-initramfs ] && \
! dd if=/dev/zero of=/tmp/check-space bs=4K count=16 2>/dev/null; then
cat <<EOF
------
Ran out of memory when unpacking initrd filesystem. Ensure your system has
at least 2 GiB RAM if booting with coreos.live.rootfs_url, or 4 GiB otherwise.
------
EOF
# Don't show logs from failed units, since they'll just be
# random misleading errors.
else
echo "Displaying logs from failed units: ${failed}"
for unit in ${failed}; do
# 10 lines should be enough for everyone
SYSTEMD_COLORS=true journalctl -b --no-pager --no-hostname -u ${unit} -n 10
done
fi
fi
}
# in SE case drop everything before entering shell
if [ -f /run/coreos/secure-execution ]; then
rm -f /run/ignition.json
rm -f /usr/lib/ignition/user.ign
rm -f /usr/lib/coreos/ignition.asc
fi
# Print warnings/informational messages to all configured consoles on the
# machine. Code inspired by https://github.com/dracutdevs/dracut/commit/32f68c1
MESSAGE="$(_display_relevant_errors)"
while read -r _tty rest; do
echo -e "$MESSAGE" > /dev/"$_tty"
done < /proc/consoles

View File

@ -0,0 +1,17 @@
[Unit]
Description=Dump Journal to Virtio Port
ConditionPathExists=/etc/initrd-release
ConditionPathExists=!/run/coreos/secure-execution
DefaultDependencies=false
ConditionVirtualization=|kvm
ConditionVirtualization=|qemu
Requires=systemd-journald.service
After=systemd-journald.service
After=basic.target
Before=initrd.target
[Service]
Type=oneshot
RemainAfterExit=yes
EnvironmentFile=/run/ignition.env
ExecStart=/usr/bin/ignition-virtio-dump-journal

View File

@ -0,0 +1,13 @@
#!/bin/bash
set -euo pipefail
port=/dev/virtio-ports/com.coreos.ignition.journal
if [ -e "${port}" ]; then
# Sync to backing filesystem before dumping what's there
journalctl --sync
journalctl -o json > "${port}"
# And this signals end of stream
echo '{}' > "${port}"
else
echo "Didn't find virtio port ${port}"
fi

View File

@ -0,0 +1,25 @@
#!/bin/bash
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
install_unit_wants() {
local unit="$1"; shift
local target="$1"; shift
local instantiated="${1:-$unit}"; shift
inst_simple "$moddir/$unit" "$systemdsystemunitdir/$unit"
# note we `|| exit 1` here so we error out if e.g. the units are missing
# see https://github.com/coreos/fedora-coreos-config/issues/799
systemctl -q --root="$initdir" add-wants "$target" "$instantiated" || exit 1
}
install() {
inst_multiple \
cut \
date \
dd
inst_hook emergency 99 "${moddir}/emergency-shell.sh"
inst_script "$moddir/ignition-virtio-dump-journal.sh" "/usr/bin/ignition-virtio-dump-journal"
install_unit_wants ignition-virtio-dump-journal.service emergency.target
}

View File

@ -0,0 +1,12 @@
[Journal]
# For now we are using kmsg for multiplexing output to
# multiple console devices during early boot.
#
# We do not want to use kmsg in the future as there may be sensitive
# ignition data that leaks to non-root users (by reading the kernel
# ring buffer using `dmesg`). In the future we will rely on kernel
# console multiplexing (link below) for this and will not use kmsg.
#
# https://github.com/coreos/fedora-coreos-tracker/issues/136
ForwardToKMsg=yes
MaxLevelKMsg=info

View File

@ -0,0 +1,12 @@
#!/bin/bash
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
depends() {
echo systemd
}
install() {
inst_simple "$moddir/00-journal-log-forwarding.conf" \
"/etc/systemd/journald.conf.d/00-journal-log-forwarding.conf"
}

View File

@ -0,0 +1,3 @@
# See also 10coreos-sysctl dracut module, which turns off ratelimiting in the
# initrd.
kernel.printk_devkmsg = ratelimit

View File

@ -0,0 +1,6 @@
# Hardcode persistent journal by default. journald has this "auto" behaviour
# that only makes logs persistent if `/var/log/journal` exists, which it won't
# on first boot because `/var` isn't fully populated. We should be able to get
# rid of this once we move to sysusers and create the dir in the initrd.
[Journal]
Storage=persistent

View File

@ -0,0 +1,116 @@
#!/bin/bash
export PATH="/usr/bin:/usr/sbin:${PATH}"
set -euo pipefail
. /usr/lib/coreos/generator-lib.sh
# Turn out if you boot with "root=..." $UNIT_DIR is not writable.
[ -w "${UNIT_DIR}" ] || {
echo "skipping coreos-boot-mount-generator: ${UNIT_DIR} is not writable"
exit 0
}
# If there's already an /etc/fstab entries for /boot, then this is is a non-FCOS
# system, likely RHCOS pre-4.3 (which still used Anaconda). In that case, we
# don't want to overwrite what the systemd-fstab-generator will do.
if findmnt --fstab /boot &>/dev/null; then
exit 0
fi
# Don't create mount units for /boot on live systems.
# ConditionPathExists won't work here because conditions don't affect
# the dependency on the underlying device unit.
if [ -f /run/ostree-live ]; then
exit 0
fi
add_wants() {
local name="$1"; shift
local wants_dir="${UNIT_DIR}/local-fs.target.wants"
mkdir -p "${wants_dir}"
ln -sf "../${name}" "${wants_dir}/${name}"
}
# Generate mount units that work with device mapper. The traditional
# device unit (dev-disk-by\x2dlabel...) does not work since it is not the
# device that systemd will fsck. This code ensures that if the label
# is backed by a device-mapper target the dev-mapper.*.device is used.
mk_mount() {
local mount_pt="${1}"; shift
local path="${1}"; shift
local options="${1}"; shift
local devservice=$(systemd-escape -p ${path} --suffix=service)
local unit_name=$(systemd-escape -p ${mount_pt} --suffix=mount)
cat > "${UNIT_DIR}/${unit_name}" <<EOF
# Automatically created by coreos-boot-mount-generator
[Unit]
Description=CoreOS Dynamic Mount for ${mount_pt}
Documentation=https://github.com/coreos/fedora-coreos-config
Before=local-fs.target
# uncomment to default
Requires=systemd-fsck@${devservice}
After=systemd-fsck@${devservice}
[Mount]
What=${path}
Where=${mount_pt}
Options=${options}
EOF
add_wants "${unit_name}"
}
# Copied from
# https://github.com/dracutdevs/dracut/blob/9491e599282d0d6bb12063eddbd192c0d2ce8acf/modules.d/99base/dracut-lib.sh#L586
# rather than sourcing it.
label_uuid_to_dev() {
local _dev
_dev="${1#block:}"
case "$_dev" in
LABEL=*)
echo "/dev/disk/by-label/$(echo "${_dev#LABEL=}" | sed 's,/,\\x2f,g;s, ,\\x20,g')"
;;
PARTLABEL=*)
echo "/dev/disk/by-partlabel/$(echo "${_dev#PARTLABEL=}" | sed 's,/,\\x2f,g;s, ,\\x20,g')"
;;
UUID=*)
echo "/dev/disk/by-uuid/$(echo "${_dev#UUID=}" | tr "[:upper:]" "[:lower:]")"
;;
PARTUUID=*)
echo "/dev/disk/by-partuuid/$(echo "${_dev#PARTUUID=}" | tr "[:upper:]" "[:lower:]")"
;;
esac
}
# If the root device is multipath, hook up /boot to use that too,
# based on our custom udev rules in 90-coreos-device-mapper.rules
# that creates "label found on mpath" links.
# Otherwise, use the usual by-label symlink.
# See discussion in https://github.com/coreos/fedora-coreos-config/pull/1022
bootdev=/dev/disk/by-label/boot
bootkarg=$(karg boot)
mpath=$(karg rd.multipath)
if [ -n "${mpath}" ] && [ "${mpath}" != 0 ]; then
bootdev=/dev/disk/by-label/dm-mpath-boot
# Newer nodes inject boot=UUID=..., but we support a larger subset of the dracut/fips API
elif [ -n "${bootkarg}" ]; then
# Adapted from https://github.com/dracutdevs/dracut/blob/9491e599282d0d6bb12063eddbd192c0d2ce8acf/modules.d/01fips/fips.sh#L17
case "$bootkarg" in
LABEL=* | UUID=* | PARTUUID=* | PARTLABEL=*)
bootdev="$(label_uuid_to_dev "$bootkarg")";;
/dev/*) bootdev=$bootkarg;;
*) echo "Unknown boot karg '${bootkarg}'; falling back to ${bootdev}";;
esac
# This is used for the first boot only
elif [ -f /run/coreos/bootfs_uuid ]; then
bootdev=/dev/disk/by-uuid/$(cat /run/coreos/bootfs_uuid)
fi
# We mount read-only by default mostly to protect
# against accidental damage. Only a few things
# owned by CoreOS should be touching /boot or the ESP.
# Use nodev,nosuid because some hardening guides want
# that even though it's of minimal value.
mk_mount /boot "${bootdev}" ro,nodev,nosuid

View File

@ -0,0 +1,87 @@
#!/bin/bash
set -euo pipefail
. /usr/lib/coreos/generator-lib.sh
write_dropin() {
local service="$1"; shift
local args="$1"; shift
local out_dir="${UNIT_DIR}/${service}.d"
mkdir -p "${out_dir}"
# /tmp isn't r/w yet, and the shell needs to cache the here-document
TMPDIR=/run
cat > "${out_dir}/10-autologin.conf" <<EOF
[Service]
ExecStart=
ExecStart=-/sbin/agetty --autologin core -o '-p -f core' ${args} %I \$TERM
EOF
}
write_interactive_live_motd() {
# Write motd to a tmp file and not directly to /etc/motd because
# SELinux denies write from init_t to etc_t
cat <<EOF > /run/interactive-live-motd
###########################################################################
Welcome to the CoreOS live environment. This system is running completely
from memory, making it a good candidate for hardware discovery and
installing persistently to disk. Here is an example of running an install
to disk via coreos-installer:
sudo coreos-installer install /dev/sda \\
--ignition-url https://example.com/example.ign
You may configure networking via 'sudo nmcli' or 'sudo nmtui' and have
that configuration persist into the installed system by passing the
'--copy-network' argument to 'coreos-installer install'. Please run
'coreos-installer install --help' for more information on the possible
install options.
###########################################################################
EOF
# Create coreos-cp-interactive-live-motd.service to copy over the motd in
# place. Note this intentionally overwrites the existing motd, which is
# blank on FCOS and populated on RHCOS.
service="coreos-cp-interactive-live-motd.service"
cat <<EOF > "${UNIT_DIR}/${service}"
# generated by coreos-liveiso-autologin-generator
[Unit]
Description=Copy CoreOS Interactive Live MOTD
Before=systemd-user-sessions.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/cp -v /run/interactive-live-motd /etc/motd
EOF
mkdir -p "${UNIT_DIR}/multi-user.target.wants"
ln -sf "../${service}" "${UNIT_DIR}/multi-user.target.wants/"
}
# Only allow automatic autologin on live systems
if [ ! -e /run/ostree-live ]; then
exit 0
fi
# Autologin on ISO boots but not PXE boots. The only way to tell the
# difference is a kernel argument.
if ! have_karg coreos.liveiso; then
exit 0
fi
# If the user supplied an Ignition config, they have the ability to enable
# autologin themselves. Don't automatically render them insecure, since
# they might be running in production and booting via e.g. IPMI.
if jq -e .userConfigProvided /etc/.ignition-result.json &>/dev/null; then
exit 0
fi
write_dropin "getty@.service" "--noclear"
# Also autologin on serial console if someone enables that
write_dropin "serial-getty@.service" "--keep-baud 115200,38400,9600"
# Write an motd that will let the user know about the live environment
# and what is possible.
write_interactive_live_motd

View File

@ -0,0 +1,66 @@
#!/usr/bin/bash
# This systemd.generator(7) detects if rescue or emergency targets were
# requested from the kernel cmdline; if so, it overrides the respective
# target to set force sulogin, allowing use of rescue/emergency targets
# on systems with locked root password (as is Fedora default).
#
# This does NOT bypass locked root password on a fsck failure, but WILL
# bypass when rescue/emergency targets are chosen from kernel cmdline.
# Since this requires console/grub access, it is assumed to be at least
# as secure as a user reset of the root password using grub to modify
# the kernel cmdline with init=/bin/bash .
#
# NOTE: the SYSTEMD_SULOGIN_FORCE method used here does not bypass any
# assigned password; root password is only bypassed when locked/unset.
export PATH="/usr/bin:/usr/sbin:${PATH}"
if [ -n "$1" ]; then
# If invoked with arguments (not testing) log to kmsg
# https://github.com/systemd/systemd/issues/15638
exec 1>/dev/kmsg; exec 2>&1
fi
# If invoked with no arguments (for testing) write to /tmp
UNIT_DIR="${1:-/tmp}"
set -euo pipefail
have_some_karg() {
local args=("$@")
IFS=" " read -r -a cmdline <<< "$(</proc/cmdline)"
local i
for i in "${cmdline[@]}"; do
for a in "${args[@]}"; do
if [[ "$i" == "$a" ]]; then
return 0
fi
done
done
return 1
}
write_dropin() {
local service="$1"
local out_dir="${UNIT_DIR}/${service}.service.d"
mkdir -p "${out_dir}"
# /tmp isn't r/w yet, and the shell needs to cache the here-document
TMPDIR=/run
cat > "${out_dir}/sulogin-force.conf" <<EOF
# Automatically created by coreos-sulogin-force-generator
[Service]
Environment=SYSTEMD_SULOGIN_FORCE=1
EOF
echo "$(basename ${0}): set SYSTEMD_SULOGIN_FORCE=1 for ${service}.service"
}
# Match kernel command line targets for systemd(1) rescue/emergency
# Ignores 'rd.' prefixed targets since they enter the dracut ramdisk
# environment which does not interact with installed system root user.
if have_some_karg 'systemd.unit=rescue.target' rescue single s S 1; then
write_dropin rescue
elif have_some_karg 'systemd.unit=emergency.target' emergency '-b' ; then
write_dropin emergency
fi

View File

@ -0,0 +1,16 @@
# This file contains overrides for systemd services that are
# enabled by default, but conflict with things we ship.
# We don't have swap by default, and systemd-oomd hard requires it.
disable systemd-oomd.service
# Disable systemd-firstboot because it conflicts with Ignition.
# In most cases this is handled via the remove-from-packages
# bits in the manifest (ignition-and-ostree.yaml), but
# we want to support overlaying builds of systemd from git.
disable systemd-firstboot.service
# This hasn't been tested with ostree/rpm-ostree and heavily overlaps
# with the latter. Preemptively disable the service; it will hopefully
# be subpackaged though for Fedora.
disable systemd-sysext.service

View File

@ -0,0 +1,34 @@
# Presets here that eventually should live in the generic fedora presets
# console-login-helper-messages - https://github.com/coreos/console-login-helper-messages
# enable console-login-helper-messages-gensnippet-os-release.service
# enable console-login-helper-messages-gensnippet-ssh-keys.service
# CA certs (probably to add to base fedora eventually)
# enable coreos-update-ca-trust.service
# Set kernel console log level
enable coreos-printk-quiet.service
# https://github.com/coreos/ignition/issues/1125
enable coreos-ignition-firstboot-complete.service
# Delete Ignition config from provider on platforms where it's possible
# https://github.com/coreos/ignition/pull/1350
enable ignition-delete-config.service
# Delete Ignition config from provider when upgrading existing nodes
enable coreos-ignition-delete-config.service
# Boot checkin services for cloud providers.
enable afterburn-checkin.service
enable afterburn-firstboot-checkin.service
# Target to write SSH key snippets from cloud providers.
enable afterburn-sshkeys.target
# Update agent
enable zincati.service
# Testing aid
enable coreos-liveiso-success.service
# See bootupd.yaml
enable bootupd.socket
# Enable rtas_errd for ppc64le to discover dynamically attached pci devices - https://bugzilla.redhat.com/show_bug.cgi?id=1811537
# The event for the attached device comes as a diag event.
# Ideally it should have been added as part of base Fedora - but since it was arch specific, it was not added: https://bugzilla.redhat.com/show_bug.cgi?id=1433859
enable rtas_errd.service
enable clevis-luks-askpass.path
# Provide status information about the Ignition run
enable coreos-ignition-write-issues.service

View File

@ -0,0 +1,28 @@
# Can be removed from FCOS in Fedora 37 or after the next barrier release,
# whichever comes first. Can be removed from RHCOS in the first release
# after every node is guaranteed to have booted at least once with 4.11 or
# higher.
[Unit]
Description=CoreOS Delete Ignition Config From Hypervisor
Documentation=https://coreos.github.io/ignition/
ConditionKernelCommandLine=|ignition.platform.id=virtualbox
ConditionKernelCommandLine=|ignition.platform.id=vmware
ConditionPathExists=!/var/lib/coreos-ignition-delete-config.stamp
# Hack: if the user masked ignition-delete-config.service, we shouldn't run
# either.
ConditionPathIsSymbolicLink=!/etc/systemd/system/ignition-delete-config.service
# We check a stamp file written by ignition-delete-config.service. That
# service runs Before=sysinit.target, on which we have a default dependency,
# so this is really just documentation.
After=ignition-delete-config.service
[Service]
Type=oneshot
ExecStart=/usr/libexec/coreos-ignition-delete-config
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,21 @@
[Unit]
Description=CoreOS Mark Ignition Boot Complete
Documentation=https://docs.fedoraproject.org/en-US/fedora-coreos/
ConditionKernelCommandLine=ignition.firstboot
ConditionPathExists=!/run/ostree-live
RequiresMountsFor=/boot
[Service]
Type=oneshot
RemainAfterExit=yes
# The MountFlags=slave is so we remount /boot temporarily writable;
# see https://github.com/ostreedev/ostree/issues/1265 for the bigger picture.
# This option creates a new mount namespace; from the point of view of
# everything else, /boot stays readonly. We only have a transient writable mount
# for the lifetime of the unit.
MountFlags=slave
ExecStart=/usr/libexec/coreos-ignition-firstboot-complete
[Install]
# Part of basic.target so this happens early on in firstboot
WantedBy=basic.target

View File

@ -0,0 +1,16 @@
# This service writes issue files describing status
# information about the Ignition run, which includes
# Ignition warnings and information if no Ignition
# config is provided.
[Unit]
Description=Create Ignition Status Issue Files
Before=systemd-user-sessions.service
ConditionPathExists=/etc/.ignition-result.json
[Service]
Type=oneshot
ExecStart=/usr/libexec/coreos-ignition-write-issues
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,26 @@
# This is used by our test framework in coreos-assembler
# since for the "live ISO without Ignition" case we
# don't have an easy way to test it.
[Unit]
Description=CoreOS Live ISO virtio success
Documentation=https://github.com/coreos/fedora-coreos-config
# Only run on the Live ISO, and only if there's no Ignition config
ConditionKernelCommandLine=coreos.liveiso
ConditionPathExists=!/config.ign
ConditionVirtualization=|kvm
ConditionVirtualization=|qemu
# Start running late to help ensure that the below conditional works
After=systemd-user-sessions.service
ConditionPathExists=/dev/virtio-ports/coreos.liveiso-success
[Service]
Type=simple
# Wait for a user session to start, then write a static message to the
# virtio channel, which https://github.com/coreos/coreos-assembler/pull/1330
# knows how to read. We previously did "journalctl -f ... | head -1" here,
# but RHEL 8 has systemd 239, which has
# https://github.com/systemd/systemd/issues/9374.
ExecStart=/bin/sh -c 'while [ -z "$(loginctl list-sessions --no-legend)" ]; do sleep 1; done; echo coreos-liveiso-success > /dev/virtio-ports/coreos.liveiso-success'
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,27 @@
[Unit]
Description=CoreOS: Set printk To Level 4 (warn)
Documentation=https://github.com/coreos/fedora-coreos-tracker/issues/1244
# We can run right after `/proc` being mounted at least
DefaultDependencies=no
# We run as early as possible; the only dependency we have really
# is the implicit After=systemd-journald.socket injected by the
# default of our stdout writing to the journal.
Conflicts=shutdown.target
Before=sysinit.target shutdown.target
# We want this service to read what we wrote
Before=systemd-sysctl.service
# Relatedly, we don't want to override an explicitly specified kernel argument
ConditionKernelCommandLine=!debug
ConditionKernelCommandLine=!quiet
ConditionKernelCommandLine=!loglevel
[Service]
Type=oneshot
RemainAfterExit=yes
# We need to make /run/sysctl.d if it doesn't exist and also
# ensure it has a SELinux label that works for systemd-sysctl.service.
# Then we just generate a sysctl file which is read by systemd-sysctl.service.
ExecStart=/bin/bash -euo pipefail -c 'mkdir -p /run/sysctl.d && chcon --reference=/etc/sysctl.d /run/sysctl.d && echo "kernel.printk = 4" > /run/sysctl.d/01-coreos-printk.conf'
[Install]
WantedBy=sysinit.target

View File

@ -0,0 +1,31 @@
# This service is currently specific to Fedora CoreOS,
# but we may want to add it to the base OS in the future.
# The idea here is to allow users to just drop in CA roots
# via Ignition without having to know to run the special
# update command.
[Unit]
Description=Run update-ca-trust
ConditionFirstBoot=true
# All services which use ConditionFirstBoot=yes should use
# Before=first-boot-complete.target, which is a target that
# was introduced in https://github.com/systemd/systemd/issues/4511
# and hasn't propagated everywhere yet. Once the target propagates
# everywhere, we can drop the systemd-machine-id-commit.service
# from the Before= line.
Before=first-boot-complete.target systemd-machine-id-commit.service
Wants=first-boot-complete.target
ConditionDirectoryNotEmpty=/etc/pki/ca-trust/source/anchors/
# We want to run quite early, in particular before anything
# that may speak TLS to external services. In the future,
# it may make sense to do this in the initramfs too.
DefaultDependencies=no
After=local-fs.target
Requires=local-fs.target
[Service]
ExecStart=/usr/bin/update-ca-trust extract
Type=oneshot
RemainAfterExit=yes
[Install]
WantedBy=basic.target

View File

@ -0,0 +1,7 @@
# Create a flag file to notify coreos-ignition-delete-config.service that
# we've run, and put it in /run because /var isn't mounted yet.
# coreos-ignition-delete-config.service will then avoid trying to delete
# the config again, and will create a persistent stamp file in /var/lib.
[Service]
ExecStart=/bin/touch /run/coreos-ignition-delete-config.stamp

View File

@ -0,0 +1,4 @@
# Temporary fix for https://github.com/coreos/fedora-coreos-tracker/issues/975
# until https://github.com/ostreedev/ostree/issues/2115 is fixed.
[Unit]
After=ostree-remount.service

View File

@ -0,0 +1,5 @@
# See the comment in 40-coreos-systemd.preset; we're
# keeping this even stronger disable override for now,
# but it may not really be necessary.
[Unit]
ConditionPathExists=/run/nosuchfile

View File

@ -0,0 +1,2 @@
d /var/spool/cron 3730 root crontab - -
d /var/spool/at 1770 root crontab - -

View File

@ -0,0 +1,16 @@
d /var/log/journal 0755 root root -
L /var/home - - - - ../home
d /var/srv 0755 root root -
d /var/roothome 0700 root root -
d /var/usrlocal 0755 root root -
d /var/usrlocal/bin 0755 root root -
d /var/usrlocal/etc 0755 root root -
d /var/usrlocal/games 0755 root root -
d /var/usrlocal/include 0755 root root -
d /var/usrlocal/lib 0755 root root -
d /var/usrlocal/man 0755 root root -
d /var/usrlocal/sbin 0755 root root -
d /var/usrlocal/share 0755 root root -
d /var/usrlocal/src 0755 root root -
d /var/mnt 0755 root root -
d /run/media 0755 root root -

View File

@ -0,0 +1,79 @@
d /var/adm 0755 root root - -
d /var/cache/bpf 0755 root root - -
d /var/cache/fwupd 0755 root root - -
d /var/cache/krb5rcache 0755 root root - -
d /var/cache/ldconfig 0700 root root - -
d /var/crash 0755 root root - -
d /var/db 0755 root root - -
d /var/db/sudo 0700 root root - -
d /var/db/sudo/lectured 0700 root root - -
d /var/empty 0755 root root - -
d /var/ftp 0755 root root - -
d /var/games 0755 root root - -
d /var/kerberos 0755 root root - -
d /var/kerberos/krb5 0755 root root - -
d /var/kerberos/krb5/user 0755 root root - -
d /var/lib/NetworkManager 0700 root root - -
L /var/lib/alternatives - - - - ../../usr/lib/alternatives
d /var/lib/authselect 0755 root root - -
d /var/lib/chrony 0750 chrony chrony - -
d /var/lib/containerd 0755 root root - -
d /var/lib/containerd/opt 0755 root root - -
d /var/lib/containers/sigstore 0755 root root - -
d /var/lib/dnsmasq 0755 root dnsmasq - -
d /var/lib/fwupd 0755 root root - -
d /var/lib/games 0755 root root - -
d /var/lib/initramfs 0755 root root - -
d /var/lib/iscsi 0755 root root - -
d /var/lib/iscsi/ifaces 0755 root root - -
d /var/lib/iscsi/isns 0755 root root - -
d /var/lib/iscsi/nodes 0755 root root - -
d /var/lib/iscsi/send_targets 0755 root root - -
d /var/lib/iscsi/slp 0755 root root - -
d /var/lib/iscsi/static 0755 root root - -
d /var/lib/kdump 0755 root root - -
d /var/lib/logrotate 0755 root root - -
d /var/lib/misc 0755 root root - -
d /var/lib/nfs/rpc_pipefs 0555 root root - -
d /var/lib/nfs/statd 0700 rpcuser rpcuser - -
d /var/lib/nfs/statd/sm 0700 rpcuser rpcuser - -
d /var/lib/nfs/statd/sm.bak 0700 rpcuser rpcuser - -
d /var/lib/os-prober 0755 root root - -
d /var/lib/polkit-1 0750 root polkitd - -
d /var/lib/polkit-1/localauthority 0755 root root - -
d /var/lib/polkit-1/localauthority/10-vendor.d 0755 root root - -
d /var/lib/polkit-1/localauthority/20-org.d 0755 root root - -
d /var/lib/polkit-1/localauthority/30-site.d 0755 root root - -
d /var/lib/polkit-1/localauthority/50-local.d 0755 root root - -
d /var/lib/polkit-1/localauthority/90-mandatory.d 0755 root root - -
d /var/lib/samba 0755 root root - -
d /var/lib/samba/lock 0755 root root - -
d /var/lib/samba/private 0700 root root - -
d /var/lib/selinux 0755 root root - -
d /var/lib/selinux/targeted 0755 root root - -
d /var/lib/selinux/tmp 0755 root root - -
d /var/lib/sss 0755 root root - -
d /var/lib/sss/db 0700 root root - -
d /var/lib/sss/deskprofile 0751 root root - -
d /var/lib/sss/gpo_cache 0755 root root - -
d /var/lib/sss/keytabs 0700 root root - -
d /var/lib/sss/mc 0775 root root - -
d /var/lib/sss/pipes 0755 root root - -
d /var/lib/sss/pipes/private 0750 root root - -
d /var/lib/sss/pubconf 0755 root root - -
d /var/lib/sss/pubconf/krb5.include.d 0755 root root - -
d /var/lib/sss/secrets 0700 root root - -
d /var/lib/systemd/catalog 0755 root root - -
d /var/local 0755 root root - -
d /var/log/audit 0700 root root - -
d /var/log/chrony 0750 chrony chrony - -
d /var/log/samba 0700 root root - -
d /var/log/samba/old 0700 root root - -
d /var/log/sssd 0750 root root - -
L /var/mail - - - - spool/mail
d /var/nis 0755 root root - -
d /var/opt 0755 root root - -
d /var/preserve 0755 root root - -
d /var/spool/lpd 0755 root root - -
d /var/spool/mail 0775 root mail - -
d /var/yp 0755 root root - -

View File

@ -0,0 +1 @@
d /var/resolv/etc 0755 root root - -

View File

@ -0,0 +1,4 @@
# Use C! according to https://github.com/coreos/fedora-coreos-config/pull/137/files#diff-4c7caeddac3f43acdf59b41ffa4e3533bb846d2e3bfa31f885a65e9598a2c4a1R1-R2
C! /var/roothome/.bashrc - - - - /usr/etc/skel/.bashrc
C! /var/roothome/.bash_profile - - - - /usr/etc/skel/.bash_profile
C! /var/roothome/.bash_logout - - - - /usr/etc/skel/.bash_logout

View File

@ -0,0 +1,2 @@
d /var/log/alt-ostree 0755 zincati zincati - -
d /run/zincati/public 0755 zincati zincati - -

View File

@ -0,0 +1,27 @@
# CoreOS-specific symlinks for dm-multipath filesystem labels,
# used for `label=boot` and `label=root`.
ACTION=="remove", GOTO="dm_label_end"
SUBSYSTEM!="block", GOTO="dm_label_end"
KERNEL!="dm-*", GOTO="dm_label_end"
# Ensure that the device mapper target is active
ENV{DM_SUSPENDED}=="1", GOTO="dm_label_end"
# Only act on filesystems. This should prevent layered devices
# such as Raid on Multipath devices from appearing.
ENV{ID_FS_USAGE}!="filesystem", GOTO="dm_label_end"
# And if the filesystem doesn't have a label+uuid, we're done.
ENV{ID_FS_LABEL_ENC}!="?*", GOTO="dm_label_end"
ENV{ID_FS_UUID_ENC}!="?*", GOTO="dm_label_end"
# Setup up Multipath labels and UUID's. Match on DM_UUID which
# is stable regardless of whether friendly names are used or not.
# 66-kpartx.rules use DM_UUID to match for linear mappings on multipath
# targets.
ENV{DM_UUID}=="*mpath*" \
, SYMLINK+="disk/by-label/dm-mpath-$env{ID_FS_LABEL_ENC}" \
, SYMLINK+="disk/by-uuid/dm-mpath-$env{ID_FS_UUID_ENC}"
LABEL="dm_label_end"

View File

@ -0,0 +1,23 @@
#!/bin/bash
set -euo pipefail
IFS=" " read -r -a cmdline <<< "$(</proc/cmdline)"
cmdline_arg() {
local name="$1" value
for arg in "${cmdline[@]}"; do
if [[ "${arg%%=*}" == "${name}" ]]; then
value="${arg#*=}"
fi
done
echo "${value}"
}
# Avoid running again if ignition-delete-config.service has run, but still
# create our own stamp file now that /var is mounted.
if [ ! -e /run/coreos-ignition-delete-config.stamp ]; then
PLATFORM_ID=$(cmdline_arg ignition.platform.id)
/usr/libexec/ignition-rmcfg --platform=${PLATFORM_ID}
fi
touch /var/lib/coreos-ignition-delete-config.stamp

View File

@ -0,0 +1,20 @@
#!/bin/bash
set -euo pipefail
mount -o remount,rw /boot
# We're done provisioning. Remove the whole /boot/ignition directory if present,
# which may include a baked Ignition config. See
# https://github.com/coreos/fedora-coreos-tracker/issues/889.
rm -rf /boot/ignition
# Regarding the lack of `-f` for rm ; we should have only run if GRUB detected
# this file. Fail if we are unable to remove it, rather than risking rerunning
# Ignition at next boot.
rm /boot/ignition.firstboot
# For ALT Linux is not required for now
# rdcore zipl checks for /boot/ignition.firstboot
# if [[ $(uname -m) = s390x ]]; then
# /usr/lib/dracut/modules.d/50rdcore/rdcore zipl --boot-mount=/boot
# fi

View File

@ -0,0 +1,71 @@
#!/usr/bin/bash
set -euo pipefail
IGNITION_RESULT=/etc/.ignition-result.json
WARN='\033[0;33m' # yellow
RESET='\033[0m' # reset
mkdir -p /run/issue.d
touch /run/issue.d/30_coreos_ignition_provisioning.issue
d=$(date --date "$(jq -r .provisioningDate "${IGNITION_RESULT}")" +"%Y/%m/%d %H:%M:%S %Z")
ignitionBoot=$(jq -r .provisioningBootID "${IGNITION_RESULT}")
if [ $(cat /proc/sys/kernel/random/boot_id) = "${ignitionBoot}" ]; then
echo "Ignition: ran on ${d} (this boot)" \
> /run/issue.d/30_coreos_ignition_provisioning.issue
# checking for /run/ostree-live as the live system with persistent storage can run Ignition more than once
if ! test -f /run/ostree-live && jq -e .previousReport.provisioningDate "${IGNITION_RESULT}" &>/dev/null; then
prevdate=$(date --date "$(jq -r .previousReport.provisioningDate "${IGNITION_RESULT}")" +"%Y/%m/%d %H:%M:%S %Z")
cat << EOF > /etc/issue.d/30_coreos_ignition_run_more_than_once.issue
${WARN}
############################################################################
WARNING: Ignition previously ran on ${prevdate}. Unexpected
behavior may occur. Ignition is not designed to run more than once per system.
############################################################################
${RESET}
EOF
fi
# In Ignition, we've two config validation checks, the one after
# fetching a config and the second after merging configs. Sometimes,
# a warning goes away after merging, however, it's possible that a
# warning appears in case merging creates a contradiction between
# two fields. So this workflow eventually sends duplicate warnings
# in journal entries. Hence, we need to avoid displaying duplicate
# Ignition warnings on the console.
# For e.g. In the journal entries, we might see the following logs:
#
# warning at $.systemd.units.0.contents, line 1 col 997: unit "echo@.service" is enabled, but has no install section so enable does nothing
# warning at $.systemd.units.0.contents: unit "echo@.service" is enabled, but has no install section so enable does nothing
#
# In order to normalize these logs, we'd need to get rid of the line
# and column numbers entirely using the sed command, and then use
# `sort -u` to remove duplicate content. After this, we'd see the
# following warning on the console:
#
# warning at $.systemd.units.0.contents: unit "echo@.service" is enabled, but has no install section so enable does nothing
#
# TODO: find a way to query journal entries recorded before the
# system switches to real root
journalctl -t ignition -o cat -p warning | sed -r 's/, line [0-9]+ col [0-9]+//g' | sort -u | while read line; do
echo -e "${WARN}Ignition: $line${RESET}" >> /etc/issue.d/30_coreos_ignition_warnings.issue
done
else
nreboots=$(($(journalctl --list-boots | wc -l) - 1))
[ "${nreboots}" -eq 1 ] && boot="boot" || boot="boots"
echo "Ignition: ran on ${d} (at least $nreboots $boot ago)" \
> /run/issue.d/30_coreos_ignition_provisioning.issue
fi
if jq -e .userConfigProvided "${IGNITION_RESULT}" &>/dev/null; then
echo "Ignition: user-provided config was applied" \
>> /run/issue.d/30_coreos_ignition_provisioning.issue
else
echo -e "${WARN}Ignition: no config provided by user${RESET}" \
>> /run/issue.d/30_coreos_ignition_provisioning.issue
fi
# Our makeshift way of getting /run/issue.d semantics. See:
# https://github.com/coreos/console-login-helper-messages/blob/e06fc88ae8fbcc3a422bc8c686f70c15aebb9d9a/usr/lib/console-login-helper-messages/issue.defs#L8-L17
ln -sf /run/issue.d/30_coreos_ignition_provisioning.issue /etc/issue.d/

View File

@ -0,0 +1,17 @@
#!/usr/bin/bash
set -eou pipefail
mkdir -m 0775 /sysroot
ln -s sysroot/ostree /ostree
mv -f /root /var/roothome
mv -f /usr/local /var/usrlocal
ln -sf var/roothome /root
ln -sf ../var/usrlocal /usr/local
mkdir -p /etc/ostree/remotes.d
echo "
[remote \"altcos\"]
url=$GLOBAL_CINCINNATI_URL/streams/$GLOBAL_BRANCH/$GLOBAL_ARCH/ostree/archive
gpg-verify=false
" > /etc/ostree/remotes.d/altcos.conf

View File

@ -0,0 +1,112 @@
#!/usr/bin/bash
set -eou pipefail
# Split passwd file (/etc/passwd) into
# /usr/etc/passwd - home users password file (uid >= 500)
# /lib/passwd - system users password file (uid < 500)
function split_passwd() {
local from_pass=$1
local sys_pass=$2
local user_pass=$3
touch "$sys_pass"
touch "$user_pass"
set -f
local ifs=$IFS
exec < "$from_pass"
while read -r line
do
IFS=:
# shellcheck disable=SC2086
set -- $line
IFS=$ifs
user=$1
uid=$3
if [[ $uid -ge 500 || $user = "root" || $user = "systemd-network" ]]
then
echo "$line" >> "$user_pass"
else
echo "$line" >> "$sys_pass"
fi
done
}
# Split group file (/etc/group) into
# /usr/etc/group - home users group file (uid >= 500)
# /lib/group - system users group file (uid < 500)
function split_group() {
local from_group=$1
local sys_group=$2
local user_group=$3
touch "$sys_group"
touch "$user_group"
set -f
local ifs=$IFS
exec < "$from_group"
while read -r line
do
IFS=:
# shellcheck disable=SC2086
set -- $line
IFS="$ifs"
user=$1
uid=$3
if [[ $uid -ge 500 ||
$user = "root" ||
$user = "adm" ||
$user = "wheel" ||
$user = "systemd-network" ||
$user = "systemd-journal" ||
$user = "docker" ]]
then
echo "$line" >> "$user_group"
else
echo "$line" >> "$sys_group"
fi
done
}
# replace "ROOT" label with "boot" at /etc/fstab
sed -i 's/^LABEL=ROOT\t/LABEL=boot\t/g' /etc/fstab
# disable "AcceptEnv" option for sshd
sed -i 's/^AcceptEnv /#AcceptEnv /g' /etc/openssh/sshd_config
# enable wheel group with all persmissions
sed -i 's/^# WHEEL_USERS ALL=(ALL) ALL$/WHEEL_USERS ALL=(ALL) ALL/g' /etc/sudoers
# change default home directory with /var/home
sed -i 's|^HOME=/home$|HOME=/var/home|g' /etc/default/useradd
# setup sshd for igntion
sed -i -e 's|#AuthorizedKeysFile\(.*\)|AuthorizedKeysFile\1 .ssh/authorized_keys.d/ignition|' \
/etc/openssh/sshd_config
ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
# setup rpm (move rpm database to [/usr]/lib/rpm)
shopt -s dotglob
mv /var/lib/rpm/* /lib/rpm
sed 's/\%{_var}\/lib\/rpm/\/lib\/rpm/' -i /usr/lib/rpm/macros
split_passwd /etc/passwd /lib/passwd /tmp/passwd.$$
mv /tmp/passwd.$$ /etc/passwd
split_group /etc/group /lib/group /tmp/group.$$
mv /tmp/group.$$ /etc/group
sed \
-e 's/passwd:.*$/& altfiles/' \
-e 's/group.*$/& altfiles/' \
-i /etc/nsswitch.conf

View File

@ -0,0 +1,9 @@
#!/usr/bin/bash
set -eou pipefail
# set cincinnati update server url
echo "
# ALTLinux CoreOS Cincinnati backend
[cincinnati]
base_url=\"$GLOBAL_CINCINNATI_URL\"
" > /etc/zincati/config.d/50-altcos-cincinnati.toml

View File

@ -0,0 +1,28 @@
#!/usr/bin/bash
set -eou pipefail
kernel=$(find /boot -type f -name "vmlinuz-*")
kmod_dir=$(find /usr/lib/modules -type d -name "*-alt*")
# move kernel to module dir
mv "$kernel" "$kmod_dir"/vmlinuz
# remove kernel symlink and initrd
rm -f /boot/vmlinuz /boot/initrd*
# re-generate initrd image
dracut \
-v \
--reproducible \
--gzip \
--add ostree \
--add ignition-ostree \
-f "$kmod_dir"/initramfs.img \
--include /etc/systemd/network/eth0.network /etc/systemd/network/eth0.network \
--kver "$(ls /usr/lib/modules)"
# shellcheck disable=SC2114
rm -rf /boot
mkdir /boot

View File

@ -0,0 +1,5 @@
#!/usr/bin/bash
set -eou pipefail
rm -rf /usr/etc
mv /etc /usr/etc

View File

@ -0,0 +1,9 @@
#!/usr/bin/bash
set -eou pipefail
# OSTree require the empty /var directory
# /var directory is populated by systemd
# shellcheck disable=SC2114
rm -rf /var
mkdir /var

4
target.toml Normal file
View File

@ -0,0 +1,4 @@
osname = "altcos"
kind = "base"
architectures = [ "x86_64" ]
branches = [ "sisyphus" ]