# Build sdme from source with vendored crate dependencies. # # sdme is a leaf application, so its transitive crate dependencies are bundled # into the SRPM as a vendor tarball (Source1) rather than packaged as separate # rust-* crates. The Fedora Rust Packaging Guidelines allow this for # applications (not libraries). # # The vendor tarball is generated by the maintainer, not fetched automatically. # See packaging/fedora/build-in-container.sh and packaging/fedora/README.md. %global crate sdme Name: sdme Version: 0.21.0 Release: 1%{?dist} Summary: The systemd machine editor # sdme itself is MIT. Bundled crates carry their own (MIT/Apache-2.0-family) # licenses; the full breakdown is generated at build time into # LICENSE.dependencies and cargo-vendor.txt and shipped as %%license files. # For the official Fedora submission, replace the tag below with the combined # SPDX expression that %%cargo_license computes over the vendored tree. License: MIT URL: https://github.com/fiorix/sdme # Canonical upstream source is the crates.io release tarball (no git tag needed). Source0: %{crates_source} Source1: %{crate}-%{version}-vendor.tar.xz ExclusiveArch: %{rust_arches} BuildRequires: cargo-rpm-macros >= 25 # systemd-nspawn and machinectl are provided by systemd-container. # The >= 255 floor matches every other channel (Debian control, both PKGBUILDs, # and the binary's own "Runs on Linux with systemd >= 255"), so dnf decides at # install time instead of sdme failing at runtime. It earns its keep on el9: # Stream 9's base systemd is 252, but the CentOS Hyperscale SIG rebases it to # 260.x (.hs.el9), so one el9 RPM installs on a Hyperscale-enabled host and is # refused on a base Stream 9. Fedora and Stream 10 (257) clear it comfortably. Requires: systemd >= 255 Requires: systemd-container # qemu-nbd (from qemu-img) is only needed for QCOW2 image import; sdme checks # for it at runtime with a clear error. Suggests (not Recommends) so dnf does # not install it and its dependency chain by default; matches the Debian # package's Suggests: qemu-utils. Suggests: qemu-img %description sdme boots systemd-nspawn containers using overlayfs copy-on-write layers, with OCI registry integration and Kubernetes Pod YAML support. Default containers are overlayfs clones of the host root filesystem; rootfs images from other distributions can be imported and booted instead. Runs on Linux with systemd and requires root. %prep %autosetup -n %{crate}-%{version} -p1 # Unpack the vendored crate sources, then point cargo at them (offline build). tar -xf %{SOURCE1} %cargo_prep -v vendor %build %cargo_vendor_manifest %cargo_license_summary %{cargo_license} > LICENSE.dependencies # build.rs compiles and embeds the sdme-kube-probe binary. It spawns a nested # cargo build that inherits the vendored, offline cargo config from # %%cargo_prep, so no network access is required. # Mark this as a Copr/dnf-managed build so `sdme upgrade` defers to the package # manager instead of overwriting the rpm-owned binary. export SDME_CHANNEL=copr %cargo_build %install %cargo_install # sdme has a [lib], so %%cargo_install also stages the crate registry sources # for a -devel subpackage. This is an application-only package: drop them so the # unpackaged-files check passes and only the binary and completions ship. rm -rf %{buildroot}%{_datadir}/cargo/registry # Shell completions are emitted by the freshly built binary (no root needed). install -d %{buildroot}%{_datadir}/bash-completion/completions install -d %{buildroot}%{_datadir}/zsh/site-functions install -d %{buildroot}%{_datadir}/fish/vendor_completions.d %{buildroot}%{_bindir}/%{crate} config completions bash > %{buildroot}%{_datadir}/bash-completion/completions/%{crate} %{buildroot}%{_bindir}/%{crate} config completions zsh > %{buildroot}%{_datadir}/zsh/site-functions/_%{crate} %{buildroot}%{_bindir}/%{crate} config completions fish > %{buildroot}%{_datadir}/fish/vendor_completions.d/%{crate}.fish %check # Run the unit tests during the build (unprivileged, offline against vendor). # Unit tests do not use the embedded probe. Keep their target directory separate # so the probe-less test build cannot replace the binary staged by %%install. export CARGO_TARGET_DIR=target/package-tests export SDME_SKIP_PROBE=1 %cargo_test %files %license LICENSE %license cargo-vendor.txt %license LICENSE.dependencies %doc README.md %{_bindir}/%{crate} %{_datadir}/bash-completion/completions/%{crate} %{_datadir}/zsh/site-functions/_%{crate} %{_datadir}/fish/vendor_completions.d/%{crate}.fish %posttrans %{_bindir}/%{crate} repair-units || : %changelog * Sun Oct 04 2026 Alexandre Fiori - 0.21.0-1 - Give new overlay --userns containers an idmapped lower layer instead of pre-chowning the rootfs into the upper layer. The unit bind-mounts the lower layer read-only and idmapped under /run/sdme/idmap, mounts the overlay on it, and drops the bind. On a 228M rootfs, create --userns goes from 1.9 seconds and a 235M upper layer to 0.01 seconds and 32K. The pre-chown remains the fallback where the lower layer cannot be idmapped (util-linux older than 2.39, a filesystem without idmapped mounts, sdme inside a user namespace), and for existing containers. - Add the userns_idmap_lower config key; set it to no to always pre-chown. - File capabilities in the rootfs are preserved and honoured with an idmapped lower layer. A binary whose effective file capabilities are outside the container's bounding set, such as ping under --hardened, fails to execute. The pre-chown loses them. - Shift what sdme cp writes into a stopped container that has an idmapped lower layer, so it is owned by the container's root and not by nobody. - Host-rootfs containers boot with --userns. With the pre-chown, the create failed in the overlay's own work directory. - Refuse to start a container with an idmapped lower layer whose UID base is in use by another running machine. - Reject --oci-pod together with --userns, --hardened or --strict, in create, new and the kube commands. Inside a user namespace the app could not enter the pod's network namespace, and systemd started it outside the pod without an error. Use --pod, or --oci-pod with --private-network. - Mark a create that never finished. A create that is killed leaves INCOMPLETE=yes in the state file: sdme ps reports it, sdme start refuses it, and sdme rm removes it, also when the container directory is missing. - sdme rm removes the temp files that killed state writes left behind, and sdme ps no longer lists them as containers. * Fri Oct 02 2026 Alexandre Fiori - 0.20.1-1 - Wait out an OCI app's stop timeout when its container is stopped or removed: the pod's terminationGracePeriodSeconds for a kube pod, 90 seconds for an OCI app outside one. sdme kube delete on a running pod whose workload ignores SIGTERM timed out after 30 seconds and left the pod and its rootfs behind, and sdme stop failed the same way. - Give the container unit a stop timeout longer than the guest's when the app's stop timeout is 90 seconds or more. The host used to kill such a container after 90 seconds, which cut a longer grace period short and left the unit in failed state. - Honor stop_timeout_terminate in sdme rm and sdme fs build, which waited a fixed 30 seconds. - Queue concurrent sdme create --userns calls on the UID range lock instead of failing with "cannot lock userns/shift", and reserve the range before the lock is released, so two containers cannot be given the same one. - Remove the container again when sdme create or sdme new fails after creating it. - Replace unit files by rename instead of rewriting them in place. A start that loaded the shared template unit in the middle of a rewrite was refused as masked. A per-start -t now goes into the container's own drop-in, and the template follows the boot_timeout setting. - Reclaim a leftover unix-export mount under /run/systemd/nspawn/unix-export as well. On systemd 259 a container that had been killed could not be started again until a second attempt. - Fail a start at once, with the unit's journal, when the unit dies before systemd-nspawn registers the machine. It used to wait for the boot timeout. - Show the cause of a failed operation in the batch commands (start, stop, rm, enable, restart, pod rm, fs rm). - Find a leftover pod rootfs inside an unmounted btrfs loopback pool when sdme kube create uses the overlay backend. - Skip files that disappear from the rootfs while sdme create --userns shifts ownership, instead of failing the create. - Use a separate temp file for each atomic write, so concurrent writers of one state file cannot publish a truncated file. * Thu Oct 01 2026 Alexandre Fiori - 0.20.0-1 - Stop sdme kube apply and kube create before any copy or pull when a kube- rootfs exists that no container claims, and name the command that removes it. The create previously ran to the end and failed at the final rename with "Directory not empty". Removing a pod with sdme rm is enough to leave such a rootfs behind. - The btrfs backend no longer deletes a leftover pod rootfs silently; both backends now refuse and report it. - Let sdme kube delete remove a leftover pod rootfs when no container of that name exists, on either backend, and succeed when nothing is left. It previously failed with "container not found". It now also refuses to remove a rootfs that another container references. - Remove the pod rootfs again when container creation fails after the rootfs was built. - Emit RequiresMountsFor for the btrfs loopback pool in the [Unit] section of container drop-ins, so systemd pulls in the mount before nspawn starts. Recognized legacy drop-ins are repaired on package upgrade and by root sdme commands; the repair is idempotent and does not restart containers. * Mon Sep 14 2026 Alexandre Fiori - 0.19.1-1 - Build the static musl release binaries again. The contained copy engine reached mount identity through the libc statx wrapper, which libc gates behind a cfg that musl targets do not get, so both release targets failed to compile. Call the statx syscall directly with in-crate kernel types, which needs no statx symbol from the target libc. - Cross-compile both musl release targets in CI on every push, so this class of breakage fails before a release tag rather than after one. * Mon Sep 14 2026 Alexandre Fiori - 0.19.0-1 - Route sdme cp and fs build COPY through a descriptor-relative copy engine that pins the write root and every destination directory, rejects ancestor symlinks, and publishes only completed inodes. Symlinks and other special nodes now publish on live container roots as well, so build COPY can copy /etc/os-release and directories containing symlinks. - Reclaim leftover systemd-nspawn runtime state at /run/systemd/nspawn/ on container start and removal, after confirming through both systemd and machined that nothing of that name is running. A container killed rather than stopped cleanly previously blocked the next start of the same name. - Default Kubernetes terminationGracePeriodSeconds to 30 seconds as the spec requires. Pods that omitted the field previously inherited systemd's 90 second stop timeout. - Make forced rootfs replacement atomic and crash-recoverable, refuse replacing a rootfs referenced by any container, and require inspection of partial replacement artifacts before a later import or removal proceeds. - Refuse container removal when D-Bus cannot confirm unit state, so a connection, permission, or decoding error no longer permits teardown. - Validate OCI digests before deriving cache paths, keep layer download scratch outside the extracted tree, confine OCI app setup writes to the staging tree, and validate app ancestry before moving image entries. - Refresh dependencies and replace serde_yml. - Move reference documentation and tutorials to docs/ as plain Markdown shared by GitHub and the website. * Tue Jul 21 2026 Alexandre Fiori - 0.18.0-1 - Make rootfs imports source-first and infer names from OCI repositories, paths, and URLs; add --name for explicit aliases and actionable collision errors. - Replace positional container names on sdme create and sdme new with --name, while preserving automatic generation for omitted or empty names. - Enforce the documented 64-character limit on sdme object names. * Mon Jul 20 2026 Alexandre Fiori - 0.17.2-1 - Fail builds that cannot embed a valid Kubernetes probe instead of shipping health checks that silently cannot run. Validate the probe's ELF architecture, class, and byte order against the Cargo target. - Make probe-less test builds explicit and track all probe-related environment variables so Cargo reliably invalidates cached build-script output. * Mon Jul 20 2026 Alexandre Fiori - 0.17.1-1 - Fix the static musl builds, which 0.17.0 could not produce: the btrfs - subvolume-destroy ioctl request was typed for glibc, where it is c_ulong, - while musl declares it c_int. It is now typed libc::Ioctl, which resolves - per target. Only the cross-compiled static binaries were affected; this - Fedora package builds against glibc and was correct in 0.17.0. - Drop a deprecated libc::time_t annotation in the timestamp formatter. * Sun Jul 19 2026 Alexandre Fiori - 0.17.0-1 - Nested-operation fixes for running sdme inside a user-namespaced container: - btrfs state operations: subvolume inspection is stat-based (no privileged tree-search ioctls), deletion issues BTRFS_IOC_SNAP_DESTROY_V2 directly. - Deletion denied in nested contexts parks the subvolume in .trash instead of failing; sdme prune destroys trash entries, and sdme warns when the data-root mount lacks user_subvol_rm_allowed. - fs import --install-packages=yes works nested: the chroot /dev is staged as a tmpfs with node binds instead of binding the outer /dev. - New --storage auto (the default): selects overlay when sdme runs inside a user-namespaced container, where btrfs roots cannot boot; explicit --storage btrfs there is a hard error. - Create-time nested preflight fails fast with the named cause (mknod blocked by kernel userns rules or an outer SystemCallFilter) instead of a boot timeout. * Sat Jul 18 2026 Alexandre Fiori - 0.16.0-1 - Add btrfs storage backend support to Kubernetes pods: `sdme kube apply/create` now accept `--storage btrfs` and `--disk`, building the combined pod rootfs as a copy-on-write subvolume snapshot of `--base-fs`. - Add nested user namespace support: `--userns-nested N` and the `userns_nested_ranges` config reserve extra 64K UID/GID ranges so containers can host further namespaced workloads inside an existing user namespace. * Fri Jul 17 2026 Alexandre Fiori - 0.15.0-1 - Require systemd >= 255 explicitly, which is the version sdme has always needed, so dnf declines the install where it cannot run instead of letting it fail at runtime. Fedora and CentOS Stream 10 are unaffected. On Stream 9 (systemd 252), enable the CentOS Hyperscale SIG, which rebases systemd to 260.x; dnf then pulls it in automatically. - Packaging release: no functional changes to sdme itself. * Fri Jul 17 2026 Alexandre Fiori - 0.14.0-1 - Accept bare syscall names in --system-call-filter, alongside the @group syntax systemd-nspawn already took, and make btrfs subvolume removal recursive so nested subvolumes no longer block `sdme rm`. * Wed Jul 15 2026 Alexandre Fiori - 0.13.1-1 - Make the btrfs storage default usable: expose default_storage_backend and btrfs_pool_size in `sdme config get` and `sdme config set`, and fall back to overlay for host-rootfs containers when btrfs is the configured default (an explicit --storage btrfs on a host rootfs is still rejected). * Wed Jul 15 2026 Alexandre Fiori - 0.13.0-1 - Add a btrfs storage backend (--storage btrfs) for imported and OCI rootfs: copy-on-write subvolume snapshots enabling nested containers, native user-namespace idmapping that preserves suid and xattrs, and per-container disk quotas (--disk). Overlay remains the default backend. --disk is refused when the datadir filesystem's btrfs quotas are managed externally, since enforcement cannot be guaranteed there. * Mon Jul 14 2026 Alexandre Fiori - 0.12.1-1 - Fix --userns pre-chown stripping setuid/setgid bits (e.g. sudo) when the kernel lacks idmapped-mount support on overlayfs. The recursive UID/GID shift ran lchown without re-applying the mode, so chown's kernel-side clearing of S_ISUID/S_ISGID left setuid binaries broken after boot. The mode is now restored after the shift. * Sun Jul 12 2026 Alexandre Fiori - 0.12.0-1 - Update to 0.12.0. - Register nspawn containers with systemd-nspawn --keep-unit (plus Slice=machine.slice and DelegateSubgroup= on systemd 256+) to avoid the boot-time machined scope-creation stall. - Add an opt-in per-container restart policy (--restart no|on-failure) and make sdme stop --kill and sdme rm restart-safe. * Fri Jul 10 2026 Alexandre Fiori - 0.11.1-1 - Update to 0.11.1. - Disable self-upgrade on this Copr build: `sdme upgrade` now defers to dnf instead of overwriting the rpm-managed binary, and the background update check is suppressed. * Fri Jul 10 2026 Alexandre Fiori - 0.11.0-1 - Update to 0.11.0. * Thu Jul 09 2026 Alexandre Fiori - 0.10.3-2 - Demote qemu-img from Recommends to Suggests; only needed for QCOW2 image import, not core container operations. * Thu Jul 09 2026 Alexandre Fiori - 0.10.3-1 - Update to 0.10.3. * Wed Jul 08 2026 Alexandre Fiori - 0.10.1-1 - Initial Fedora package.