| 411 |
411 |
|
swaylock \
|
| 412 |
412 |
|
swayidle \
|
| 413 |
413 |
|
swayosd \
|
|
414 |
+ |
# Fingerprint unlock, which swaylock reaches without knowing it: its
|
|
415 |
+ |
# /etc/pam.d/swaylock is `auth include login`, login includes
|
|
416 |
+ |
# system-auth, and system-auth is what authselect rewrites when the
|
|
417 |
+ |
# with-fingerprint feature is enabled below. So the lock screen, the
|
|
418 |
+ |
# greeter and run0 all gain the same unlock from one switch, and none
|
|
419 |
+ |
# of them needs an Alloy-authored PAM file.
|
|
420 |
+ |
#
|
|
421 |
+ |
# fprintd-pam is the half that matters and is not pulled in by fprintd:
|
|
422 |
+ |
# the daemon can enroll a finger all day, but without the PAM module
|
|
423 |
+ |
# nothing ever asks it. Both named so neither arrives as somebody
|
|
424 |
+ |
# else's transitive dependency.
|
|
425 |
+ |
fprintd \
|
|
426 |
+ |
fprintd-pam \
|
| 414 |
427 |
|
playerctl \
|
| 415 |
428 |
|
gammastep \
|
| 416 |
429 |
|
# Continuity
|
| 628 |
641 |
|
jq \
|
| 629 |
642 |
|
&& dnf clean all
|
| 630 |
643 |
|
|
|
644 |
+ |
# =====================================================================
|
|
645 |
+ |
# Printing — driverless only, and deliberately in its own layer.
|
|
646 |
+ |
#
|
|
647 |
+ |
# Alloy prints to IPP Everywhere devices and nothing else. That is the
|
|
648 |
+ |
# whole position: every printer sold since roughly 2015 speaks it, the
|
|
649 |
+ |
# printer advertises its own capabilities, and there is no driver to
|
|
650 |
+ |
# pick, install or match. A printer that needs a vendor driver is not
|
|
651 |
+ |
# supported, stated plainly rather than left to be discovered.
|
|
652 |
+ |
#
|
|
653 |
+ |
# What that buys is the absence of the usual printing stack:
|
|
654 |
+ |
# foomatic-db is thousands of PPDs, gutenprint and hplip are vendor
|
|
655 |
+ |
# driver estates, and none of them is reachable from a driverless-only
|
|
656 |
+ |
# position. Verified against the resolved transaction rather than
|
|
657 |
+ |
# assumed — none of the three appears. ghostscript does, as a hard
|
|
658 |
+ |
# dependency of cups-filters for rasterizing, and is accepted.
|
|
659 |
+ |
#
|
|
660 |
+ |
# The prerequisite was already in place, which is what makes this cheap:
|
|
661 |
+ |
# discovery is mDNS, and nss-mdns is installed with /etc/nsswitch.conf
|
|
662 |
+ |
# already resolving .local (see the avahi block). So a driverless
|
|
663 |
+ |
# printer appears by itself and most users never configure anything.
|
|
664 |
+ |
#
|
|
665 |
+ |
# Weak dependencies off, and that is why this is a separate `dnf
|
|
666 |
+ |
# install` rather than more lines in the block above: on the default
|
|
667 |
+ |
# `install_weak_deps=True` this transaction is 52 packages instead of
|
|
668 |
+ |
# 33, and the extra 19 are recommends nothing here asked for. The block
|
|
669 |
+ |
# above does not pass the flag, so folding these in would have taken
|
|
670 |
+ |
# the larger set silently.
|
|
671 |
+ |
#
|
|
672 |
+ |
# No scanning. sane-backends is per-device backends and USB permission
|
|
673 |
+ |
# work, its failures are opaque, and a scanner is far rarer on a laptop
|
|
674 |
+ |
# than a printer. Recorded as a rejection in docs/STACK.md rather than
|
|
675 |
+ |
# left as silence, per principle 5.
|
|
676 |
+ |
#
|
|
677 |
+ |
# The surface is CUPS' own web UI on localhost:631. It needs no GTK and
|
|
678 |
+ |
# costs nothing when unused, which matters because socket activation
|
|
679 |
+ |
# means the daemon is not running until something connects.
|
|
680 |
+ |
# =====================================================================
|
|
681 |
+ |
RUN dnf install -y --setopt=install_weak_deps=False \
|
|
682 |
+ |
cups \
|
|
683 |
+ |
cups-filters \
|
|
684 |
+ |
&& dnf clean all
|
|
685 |
+ |
RUN set -eu; \
|
|
686 |
+ |
for unwanted in foomatic-db gutenprint hplip; do \
|
|
687 |
+ |
rpm -q "$unwanted" >/dev/null 2>&1 \
|
|
688 |
+ |
&& { echo "$unwanted arrived with the printing stack; the driverless-only position is no longer true" >&2; exit 1; }; \
|
|
689 |
+ |
done; \
|
|
690 |
+ |
test -f /usr/lib/systemd/system/cups.socket \
|
|
691 |
+ |
|| { echo "cups ships no socket unit; the preset would enable nothing and printing would need a running daemon" >&2; exit 1; }; \
|
|
692 |
+ |
echo "printing: driverless only, no vendor driver packages"
|
|
693 |
+ |
|
| 631 |
694 |
|
# SwayOSD ships its system unit where systemd does not look.
|
| 632 |
695 |
|
#
|
| 633 |
696 |
|
# Fedora's SwayOSD-0.3.2 installs swayosd-libinput-backend.service into
|
| 813 |
876 |
|
COPY usr/ /usr/
|
| 814 |
877 |
|
COPY --from=rust-build /staged-skel/ /
|
| 815 |
878 |
|
|
|
879 |
+ |
# =====================================================================
|
|
880 |
+ |
# The encrypted install path — assert bootc will actually permit it.
|
|
881 |
+ |
#
|
|
882 |
+ |
# `bootc install --block-setup tpm2-luks` is gated by the image's own
|
|
883 |
+ |
# install config, not by the hardware: with no `block` key bootc allows
|
|
884 |
+ |
# `direct` alone and refuses the flag with "tpm2-luks not enabled in
|
|
885 |
+ |
# installation config". That is exactly what happened, on a machine with
|
|
886 |
+ |
# a working TPM, because the config declared a root filesystem and
|
|
887 |
+ |
# nothing else. The installer offers encryption on step 4 and defaults
|
|
888 |
+ |
# it to on, so every user taking the default hit a dead path.
|
|
889 |
+ |
#
|
|
890 |
+ |
# Nothing failed at build time, which is why this check exists: the flag
|
|
891 |
+ |
# lives in crates/alloy/src/install.rs and the permission lives in a
|
|
892 |
+ |
# TOML file, and neither knows the other exists. The coupling is only
|
|
893 |
+ |
# observable at the moment a disk is being erased.
|
|
894 |
+ |
#
|
|
895 |
+ |
# The order check is not pedantry. bootc uses the FIRST entry as the
|
|
896 |
+ |
# default for an install that passes no --block-setup, and the installer
|
|
897 |
+ |
# omits the flag precisely when the user declined encryption. Put
|
|
898 |
+ |
# tpm2-luks first and declining encryption would hand back an encrypted
|
|
899 |
+ |
# disk whose passphrase nobody was asked for.
|
|
900 |
+ |
# =====================================================================
|
|
901 |
+ |
RUN set -eu; \
|
|
902 |
+ |
conf=/usr/lib/bootc/install/00-alloy.toml; \
|
|
903 |
+ |
test -f "$conf" \
|
|
904 |
+ |
|| { echo "$conf is missing; bootc would lose both the rootfs type and the block allowlist" >&2; exit 1; }; \
|
|
905 |
+ |
block="$(sed -n 's/^[[:space:]]*block[[:space:]]*=[[:space:]]*//p' "$conf")"; \
|
|
906 |
+ |
test -n "$block" \
|
|
907 |
+ |
|| { echo "$conf declares no 'block' key, so bootc permits 'direct' only and the installer's encryption step cannot work" >&2; exit 1; }; \
|
|
908 |
+ |
echo "$block" | grep -q 'tpm2-luks' \
|
|
909 |
+ |
|| { echo "$conf does not enable tpm2-luks: $block" >&2; exit 1; }; \
|
|
910 |
+ |
echo "$block" | grep -q '^\[[[:space:]]*"direct"' \
|
|
911 |
+ |
|| { echo "$conf must list \"direct\" first; bootc takes the first entry as the default and an unencrypted install passes no --block-setup: $block" >&2; exit 1; }; \
|
|
912 |
+ |
echo "bootc install config: block = $block"
|
|
913 |
+ |
|
|
914 |
+ |
# =====================================================================
|
|
915 |
+ |
# Fingerprint unlock — turn it on through authselect, not by hand.
|
|
916 |
+ |
#
|
|
917 |
+ |
# /etc/pam.d/system-auth is generated: on this base /etc/nsswitch.conf is
|
|
918 |
+ |
# already a symlink into authselect's tree, and hand-editing a PAM file
|
|
919 |
+ |
# authselect owns means the next `authselect apply-changes` silently
|
|
920 |
+ |
# discards it. The feature switch is the supported edit and the only one
|
|
921 |
+ |
# that survives.
|
|
922 |
+ |
#
|
|
923 |
+ |
# `sufficient` is what the feature installs, which is the property worth
|
|
924 |
+ |
# stating: a finger that does not match, a reader that is busy, or a user
|
|
925 |
+ |
# with nothing enrolled all fall through to the password prompt rather
|
|
926 |
+ |
# than locking anyone out. That matters here more than usual, because
|
|
927 |
+ |
# nothing enrolls a finger at install time — `fprintd-enroll` is a thing
|
|
928 |
+ |
# the user runs later, and until they do this changes nothing at all.
|
|
929 |
+ |
#
|
|
930 |
+ |
# Asserted rather than trusted, twice. authselect reports success for a
|
|
931 |
+ |
# feature it did not apply if the profile does not offer it, and the
|
|
932 |
+ |
# generated file is the only place the answer is visible.
|
|
933 |
+ |
#
|
|
934 |
+ |
# authselect prints "make sure fprintd service is configured and enabled"
|
|
935 |
+ |
# here. Nothing to do: fprintd is Type=dbus with BusName and a
|
|
936 |
+ |
# system-services activation file, so the first PAM call starts it. No
|
|
937 |
+ |
# preset line, for the same reason gnome-keyring does not get one.
|
|
938 |
+ |
# =====================================================================
|
|
939 |
+ |
RUN set -eu; \
|
|
940 |
+ |
authselect enable-feature with-fingerprint; \
|
|
941 |
+ |
authselect apply-changes; \
|
|
942 |
+ |
grep -q 'pam_fprintd\.so' /etc/pam.d/system-auth \
|
|
943 |
+ |
|| { echo "with-fingerprint did not reach system-auth; the lock screen would never ask the reader" >&2; exit 1; }; \
|
|
944 |
+ |
grep -q '^auth.*sufficient.*pam_fprintd\.so' /etc/pam.d/system-auth \
|
|
945 |
+ |
|| { echo "pam_fprintd is in system-auth but not as 'sufficient'; a failed or absent finger would not fall through to the password" >&2; exit 1; }; \
|
|
946 |
+ |
test -f /etc/pam.d/swaylock \
|
|
947 |
+ |
|| { echo "swaylock ships no PAM file; the include chain this relies on is gone" >&2; exit 1; }; \
|
|
948 |
+ |
echo "fingerprint: $(grep -c pam_fprintd /etc/pam.d/system-auth) pam_fprintd line(s) in system-auth"
|
|
949 |
+ |
|
| 816 |
950 |
|
# =====================================================================
|
| 817 |
951 |
|
# The session wrapper — assert it can actually run.
|
| 818 |
952 |
|
#
|
| 1054 |
1188 |
|
# run after the config tree is in place, so it lives here.
|
| 1055 |
1189 |
|
# =====================================================================
|
| 1056 |
1190 |
|
|
| 1057 |
|
- |
# SwayOSD's system unit is not where systemd looks for units. Fedora's
|
| 1058 |
|
- |
# SwayOSD 0.3.2 installs swayosd-libinput-backend.service into
|
| 1059 |
|
- |
# /usr/lib64/systemd/system, and systemd's search path is /etc/systemd/system,
|
| 1060 |
|
- |
# /usr/local/lib/systemd/system and /usr/lib/systemd/system. On this base
|
| 1061 |
|
- |
# /usr/lib64 is a real directory rather than a symlink to /usr/lib, so the
|
| 1062 |
|
- |
# unit is invisible: `systemctl enable` answers "Unit
|
| 1063 |
|
- |
# swayosd-libinput-backend.service does not exist", and the preset line for it
|
| 1064 |
|
- |
# matches nothing and says nothing. That is a packaging bug upstream, not a
|
| 1065 |
|
- |
# choice Alloy gets to make, so link the unit into the path systemd reads.
|
| 1066 |
|
- |
#
|
| 1067 |
|
- |
# Without this the caps-lock and num-lock overlays have no daemon, and the
|
| 1068 |
|
- |
# sway config's `bindsym --release Caps_Lock` does nothing at all.
|
| 1069 |
|
- |
#
|
| 1070 |
|
- |
# Written to survive the fix rather than assume the bug is permanent: if a
|
| 1071 |
|
- |
# later SwayOSD ships the unit at the canonical path, this leaves it alone
|
| 1072 |
|
- |
# instead of replacing a real unit file with a link to a file that moved. If
|
| 1073 |
|
- |
# the unit is at neither path the build stops, because the alternative is
|
| 1074 |
|
- |
# shipping the dead bind again and not knowing.
|
| 1075 |
|
- |
RUN canon=/usr/lib/systemd/system/swayosd-libinput-backend.service; \
|
| 1076 |
|
- |
real=/usr/lib64/systemd/system/swayosd-libinput-backend.service; \
|
| 1077 |
|
- |
if [ -e "$canon" ]; then \
|
| 1078 |
|
- |
echo "swayosd unit is already in the search path; the shim can go"; \
|
| 1079 |
|
- |
elif [ -e "$real" ]; then \
|
| 1080 |
|
- |
ln -s "$real" "$canon"; \
|
| 1081 |
|
- |
else \
|
| 1082 |
|
- |
echo "swayosd-libinput-backend.service is at neither path" >&2; exit 1; \
|
| 1083 |
|
- |
fi
|
| 1084 |
|
- |
|
|
1191 |
+ |
# The SwayOSD unit is already on the search path by the time preset-all runs:
|
|
1192 |
+ |
# the copy that puts it there is up with the rest of the packaging shims, next
|
|
1193 |
+ |
# to the udev rule that has the same defect. A second block used to stand here
|
|
1194 |
+ |
# doing the same job with a symlink, guarded by `if [ -e "$canon" ]`. Because
|
|
1195 |
+ |
# the copy had already created that path, the guard always took its first
|
|
1196 |
+ |
# branch and printed "the shim is already in the search path" — which read
|
|
1197 |
+ |
# like the workaround having become unnecessary, when in fact the earlier copy
|
|
1198 |
+ |
# was what satisfied it. Two fixes for one bug, landed the same day, and the
|
|
1199 |
+ |
# survivor is the one that fails the build loudly when Fedora corrects the
|
|
1200 |
+ |
# packaging rather than the one that quietly steps aside.
|
| 1085 |
1201 |
|
RUN systemctl preset-all
|
| 1086 |
1202 |
|
|
| 1087 |
1203 |
|
# Template instances have to be enabled by name. `preset-all` iterates over
|