Files
omarchy-pkgs/pkgbuilds/omarchy-settings/PKGBUILD
T
David Heinemeier HanssonandClaude Opus 5 2aa5c50e65 Install omarchy-crash-watch.service into /usr/lib/systemd/user
#6746 added the unit, the binary, the enable-user-units.sh entry, and a
migration, but not the install line here -- so omarchy-settings shipped
omarchy-crash-watch.service only into the default/ template tree and never
into the search path systemd actually reads.

install/user/first-run/enable-user-units.sh enables its six units in a single
`systemctl --user enable --now` call, so the missing unit failed the whole
call. omarchy-provision-first-run only marks first-run-user when every step
succeeds, which meant first-run never completed and replayed on every login,
re-firing the "Learn Keybindings" and "Update System" notifications. Because
enable is atomic, it also left the other five units disabled -- no bluetooth
agent, sleep lock, monitor recovery, migrate notifier, or fcitx5.

Migration 1786539345 falls back to writing the wants symlink by hand when
there is no live user manager, pointing at the /usr/lib path this omission
left empty, so existing installs got a dangling symlink too.

No new migration is needed: affected installs retry first-run on the next
login and succeed, and the dangling symlinks resolve as soon as the file
exists at that path.

test/shell.d/config-test.sh already asserts this install and fails without it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm1hEGtGRUrfqxMbTi1fWe
2026-08-12 23:08:13 +02:00

346 lines
17 KiB
Bash

# Maintainer: Ryan Hughes <ryan@omarchy.org>
# Release versioning convention (do not "fix" this; enforced by bin/omarchy-pkgs release):
# - Pre-releases use the ATTACHED form pkgver=X.Y.ZrcN — NO separator. pacman's
# vercmp orders 4.0.0rc1 < 4.0.0rc2 < 4.0.0, but 4.0.0.rc1 and 4.0.0_rc1
# both sort AFTER 4.0.0 and would strand users on the pre-release.
# - pkgrel resets to 1 whenever pkgver changes; bump pkgrel alone only to
# repackage the same source.
# - epoch is a manual escape hatch decided by a human; tooling never sets it.
# - _commit is the single source of truth for what gets built. _tag is
# provenance only (empty when cut from a bare commit). omarchy and
# omarchy-settings must always carry identical _tag/_commit/pkgver/sha256sums.
pkgname='omarchy-settings'
_tag=''
_commit='438f7b3340b3468cb82ff6e5d218b6c7ef50f165'
pkgver=4.0.0rc1
pkgrel=1
pkgdesc='Omarchy user defaults, /etc/skel content, fonts, plymouth theme, and support helpers'
arch=('any')
url='https://github.com/basecamp/omarchy'
license=('MIT')
conflicts=('omarchy-settings-dev')
# `/etc/default/limine` is intentionally NOT owned by this package. The ISO
# orchestrator generates it at install time from the resolved target boot
# cmdline. We ship a template under /usr/share/omarchy/default/limine/ for the
# orchestrator to read.
#
# limine + limine-mkinitcpio-hook + limine-snapper-sync + snapper are NOT in
# depends because this package gets installed into the live ISO env (for
# plymouth / /etc/skel seeding) where there is no ESP and the mkinitcpio hook
# would fail trying to deploy Limine. The target omarchy package pulls in the
# full bootloader/snapshot stack; omarchy-iso only installs the early Limine
# pieces needed before the runtime package lands.
depends=(
'bash'
'curl'
'gum'
'hicolor-icon-theme'
'plymouth'
)
makedepends=(
'git'
'imagemagick'
)
# backup=() is pacman's hook for protecting user edits to package-owned files
# on upgrade. Only the paths the package actually installs into /etc qualify.
# The etc-overrides set (faillock.conf, nsswitch.conf, cups-browsed.conf,
# plymouthd.conf, /etc/skel/.bashrc) ships at /usr/share/omarchy/etc-overrides/
# and is cp -f'd by post_install — those paths are unowned by pacman and the
# scriptlet WILL clobber user edits on each upgrade (documented limitation).
backup=(
'etc/fastfetch/config.jsonc'
'etc/mkinitcpio.conf.d/omarchy_hooks.conf'
'etc/mkinitcpio.conf.d/thunderbolt_module.conf'
'etc/limine-entry-tool.d/omarchy-defaults.conf'
'etc/limine-entry-tool.d/omarchy-uki.conf'
'etc/docker/daemon.json'
'etc/gnupg/dirmngr.conf'
'etc/sysctl.d/99-omarchy-sysctl.conf'
'etc/sysctl.d/90-omarchy-file-watchers.conf'
'etc/modprobe.d/omarchy-usb-autosuspend.conf'
'etc/systemd/logind.conf.d/10-ignore-power-button.conf'
'etc/systemd/logind.conf.d/20-inhibit-delay.conf'
'etc/systemd/resolved.conf.d/10-disable-multicast.conf'
'etc/systemd/resolved.conf.d/20-docker-dns.conf'
'etc/systemd/system.conf.d/10-faster-shutdown.conf'
'etc/systemd/system/user@.service.d/10-faster-shutdown.conf'
'etc/systemd/system/docker.service.d/no-block-boot.conf'
'etc/systemd/system/plocate-updatedb.service.d/ac-only.conf'
'etc/systemd/system.conf.d/20-omarchy-nofile.conf'
'etc/systemd/user.conf.d/20-omarchy-nofile.conf'
'etc/systemd/oomd.conf.d/10-omarchy.conf'
'etc/systemd/zram-generator.conf'
'etc/sddm.conf.d/10-theme.conf'
'etc/sddm.conf.d/10-wayland.conf'
'etc/udev/rules.d/99-omarchy-power-profile.rules'
'etc/udev/rules.d/99-omarchy-wifi-powersave.rules'
)
optdepends=(
'omarchy: Full Omarchy desktop'
'inxi: System information for omarchy-debug'
'fastfetch: System information for omarchy-upload-log'
'limine: Bootloader the shipped /etc/mkinitcpio.conf.d/ and /etc/limine-entry-tool.d/ drop-ins are for'
'limine-mkinitcpio-hook: Picks up the shipped /etc/mkinitcpio.conf.d/omarchy_hooks.conf'
'limine-snapper-sync: Boot-entry sync for snapper snapshots'
'zram-generator: Reads the shipped /etc/systemd/zram-generator.conf to create the compressed swap device'
'snapper: Used with the shipped /etc/snapper/config-templates/omarchy template'
)
install='omarchy-settings.install'
# Live config files the package can't own outright (the path is owned by an
# upstream Arch package): ship them at /usr/share/omarchy/etc-overrides/ and
# cp -f into place from post_install. See omarchy-settings.install.
_etc_override_paths=(
'etc/security/faillock.conf'
'etc/nsswitch.conf'
'etc/cups/cups-browsed.conf'
'etc/plymouth/plymouthd.conf'
)
# Source: the pinned release commit; set OMARCHY_SRC=/path/to/checkout to
# build from a local source tree instead (mirrors omarchy-zsh/omarchy-fish DX).
if [[ -n "${OMARCHY_SRC:-}" ]]; then
source=()
sha256sums=()
else
source=("omarchy::git+https://github.com/basecamp/omarchy.git#commit=${_commit}")
sha256sums=('56e9ee1b7326ae7c9bcf0c1247683612de2e8cd5bc54ff4bd24d047ddc9dde1e')
fi
prepare() {
if [[ -n "${OMARCHY_SRC:-}" ]]; then
rm -rf "$srcdir/omarchy"
mkdir -p "$srcdir/omarchy"
cp -a "${OMARCHY_SRC}/." "$srcdir/omarchy/"
fi
}
package() {
cd "$srcdir/omarchy"
# /etc/skel/.config from config/** — system-wide default user config.
# Package-owned defaults that live elsewhere in the system belong under
# default/** or etc/** instead.
install -d "$pkgdir/etc/skel/.config"
cp -a config/. "$pkgdir/etc/skel/.config/"
# Fastfetch reads /etc/fastfetch/config.jsonc when no user config exists.
install -Dm644 etc/fastfetch/config.jsonc "$pkgdir/etc/fastfetch/config.jsonc"
# ALSO ship config/** under /usr/share/omarchy/config/. Used as the
# source-of-truth by omarchy-refresh-config, omarchy-reinstall-configs,
# and other commands that copy individual files into a running user's
# ~/.config. /etc/skel only seeds new users; this tree is what existing
# users re-sync against.
install -d "$pkgdir/usr/share/omarchy/config"
cp -a config/. "$pkgdir/usr/share/omarchy/config/"
# Package-owned defaults with real system/XDG locations. User config remains
# higher priority: ~/.config/uwsm/default, ~/.config/uwsm/env.d,
# ~/.config/environment.d, ~/.config/fontconfig, ~/.config/xdg-terminals.list,
# ~/.config/mimeapps.list, and ~/.config/systemd/user can all override these.
install -Dm644 default/uwsm/env.d/10-omarchy "$pkgdir/usr/share/uwsm/env.d/10-omarchy"
install -Dm644 default/environment.d/10-omarchy-fcitx.conf "$pkgdir/usr/lib/environment.d/10-omarchy-fcitx.conf"
install -Dm644 default/fontconfig/conf.avail/50-omarchy.conf "$pkgdir/usr/share/fontconfig/conf.avail/50-omarchy.conf"
install -d "$pkgdir/etc/fonts/conf.d"
ln -sfn /usr/share/fontconfig/conf.avail/50-omarchy.conf "$pkgdir/etc/fonts/conf.d/50-omarchy.conf"
install -Dm644 default/xdg-terminal-exec/hyprland-xdg-terminals.list "$pkgdir/usr/share/xdg-terminal-exec/hyprland-xdg-terminals.list"
install -Dm644 default/applications/mimeapps.list "$pkgdir/usr/share/applications/mimeapps.list"
install -Dm644 default/systemd/user/bt-agent.service "$pkgdir/usr/lib/systemd/user/bt-agent.service"
install -Dm644 default/systemd/user/omarchy-sleep-lock.service "$pkgdir/usr/lib/systemd/user/omarchy-sleep-lock.service"
install -Dm644 default/systemd/user/omarchy-recover-internal-monitor.service "$pkgdir/usr/lib/systemd/user/omarchy-recover-internal-monitor.service"
install -Dm644 default/systemd/user/omarchy-migrate-notify.service "$pkgdir/usr/lib/systemd/user/omarchy-migrate-notify.service"
# Compatibility alias for the old unit name. Existing users have an absolute
# graphical-session.target.wants symlink to this path from when they were set
# up, and the migration that repoints it only runs for users who actually run
# an update -- which is the opposite of who this notifier is for. Without the
# alias their symlink dangles and they are never told about pending
# migrations. Droppable once installs have run migration 1785095882.
ln -sfn omarchy-migrate-notify.service "$pkgdir/usr/lib/systemd/user/omarchy-update-user-notify.service"
install -Dm644 default/systemd/user/omarchy-tailscale-receive.service "$pkgdir/usr/lib/systemd/user/omarchy-tailscale-receive.service"
install -Dm644 default/systemd/user/omarchy-fcitx5.service "$pkgdir/usr/lib/systemd/user/omarchy-fcitx5.service"
install -Dm644 default/systemd/user/omarchy-crash-watch.service "$pkgdir/usr/lib/systemd/user/omarchy-crash-watch.service"
# Marks app.slice (and only app.slice) as a systemd-oomd kill candidate, so
# memory pressure costs one app scope instead of the compositor session.
# Thresholds live in etc/systemd/oomd.conf.d/10-omarchy.conf.
install -Dm644 default/systemd/user/app.slice.d/10-oomd.conf "$pkgdir/usr/lib/systemd/user/app.slice.d/10-oomd.conf"
install -Dm644 default/systemd/zram-generator.conf.d/90-omarchy.conf "$pkgdir/usr/lib/systemd/zram-generator.conf.d/90-omarchy.conf"
# Same for applications/** — used by omarchy-refresh-applications,
# omarchy-install-gaming-*, etc. to copy .desktop files into ~/.local/share.
install -d "$pkgdir/usr/share/omarchy/applications"
cp -a applications/. "$pkgdir/usr/share/omarchy/applications/"
# Icons are package-owned below in /usr/share/icons/hicolor, not this
# historical app-local folder.
rm -rf "$pkgdir/usr/share/omarchy/applications/icons"
# /etc tree (drop-ins the package fully owns + the etc-override files we
# stage separately below).
install -d "$pkgdir/etc"
cp -a etc/. "$pkgdir/etc/"
# sudoers.d files must be mode 0440 or sudo will refuse them, and the
# directory must be 0750 to match the Arch sudo package's filesystem
# convention (otherwise pacman warns about dir-mode drift on every install).
if [[ -d "$pkgdir/etc/sudoers.d" ]]; then
chmod 0750 "$pkgdir/etc/sudoers.d"
chmod 0440 "$pkgdir/etc/sudoers.d"/*
fi
# Stage upstream-owned files at /usr/share/omarchy/etc-overrides/ instead of
# owning their live /etc paths directly (which would conflict with pam,
# filesystem, cups-browsed, plymouth, bash). post_install copies them in.
install -d "$pkgdir/usr/share/omarchy/etc-overrides"
install -Dm644 default/bashrc \
"$pkgdir/usr/share/omarchy/etc-overrides/dot.bashrc"
cat >"$pkgdir/usr/share/omarchy/etc-overrides/os-release" <<EOF
NAME="Omarchy"
PRETTY_NAME="Omarchy"
ID=omarchy
ID_LIKE=arch
BUILD_ID="$pkgver"
VERSION_ID="$pkgver"
ANSI_COLOR="38;2;158;206;106"
HOME_URL="https://omarchy.org/"
DOCUMENTATION_URL="https://learn.omacom.io/2/the-omarchy-manual"
SUPPORT_URL="https://discord.gg/tXFUdasqhY"
BUG_REPORT_URL="https://github.com/basecamp/omarchy/issues"
LOGO=omarchy
EOF
for path in "${_etc_override_paths[@]}"; do
case "$path" in
'etc/security/faillock.conf')
mv "$pkgdir/$path" "$pkgdir/usr/share/omarchy/etc-overrides/security-faillock.conf" ;;
'etc/nsswitch.conf')
mv "$pkgdir/$path" "$pkgdir/usr/share/omarchy/etc-overrides/nsswitch.conf" ;;
'etc/cups/cups-browsed.conf')
mv "$pkgdir/$path" "$pkgdir/usr/share/omarchy/etc-overrides/cups-cups-browsed.conf" ;;
'etc/plymouth/plymouthd.conf')
mv "$pkgdir/$path" "$pkgdir/usr/share/omarchy/etc-overrides/plymouth-plymouthd.conf" ;;
esac
done
# The directories under /etc we just emptied are upstream-owned; remove our
# empty placeholders so pacman doesn't complain.
rmdir "$pkgdir/etc/security" 2>/dev/null || true
rmdir "$pkgdir/etc/cups" 2>/dev/null || true
rmdir "$pkgdir/etc/plymouth" 2>/dev/null || true
# /etc/skel/.local/share/applications from applications/**.
install -d "$pkgdir/etc/skel/.local/share/applications"
if compgen -G 'applications/*.desktop' >/dev/null; then
cp applications/*.desktop "$pkgdir/etc/skel/.local/share/applications/"
fi
if [[ -d applications/hidden ]] && compgen -G 'applications/hidden/*.desktop' >/dev/null; then
cp applications/hidden/*.desktop "$pkgdir/etc/skel/.local/share/applications/"
fi
# Package-owned application icons in standard freedesktop hicolor paths.
# Desktop files and generated webapp/TUI launchers reference these by icon
# name, so user setup no longer needs to copy static Omarchy icons into
# ~/.local/share.
if [[ -d applications/icons ]] && compgen -G 'applications/icons/*' >/dev/null; then
install -d "$pkgdir/usr/share/icons/hicolor/256x256/apps"
install -d "$pkgdir/usr/share/icons/hicolor/48x48/apps"
for icon in applications/icons/*; do
[[ -f $icon ]] || continue
icon_name=$(basename "$icon")
icon_id=$(printf '%s\n' "${icon_name%.*}" \
| tr '[:upper:]' '[:lower:]' \
| sed 's/[^[:alnum:]]\+/-/g; s/^-//; s/-$//')
case "$icon_name" in
*.svg)
install -Dm644 "$icon" "$pkgdir/usr/share/icons/hicolor/scalable/apps/$icon_id.svg"
;;
*)
magick "$icon" -thumbnail 256x256 -background transparent -gravity center -extent 256x256 \
"PNG32:$pkgdir/usr/share/icons/hicolor/256x256/apps/$icon_id.png"
magick "$icon" -thumbnail 48x48 -background transparent -gravity center -extent 48x48 \
"PNG32:$pkgdir/usr/share/icons/hicolor/48x48/apps/$icon_id.png"
;;
esac
done
fi
# default/** ships to /usr/share/omarchy/default/. The Snapper template is
# additionally installed to /etc/snapper/config-templates/ for the standard
# Snapper template location; Omarchy target setup copies the default into the
# live root config.
install -d "$pkgdir/usr/share/omarchy/default"
cp -a default/. "$pkgdir/usr/share/omarchy/default/"
# Snapper config template used by the install-time `snapper create-config`.
install -Dm644 default/snapper/root \
"$pkgdir/etc/snapper/config-templates/omarchy"
# SDDM theme/session assets. These are static package-owned files; the
# installer only writes autologin.conf because that embeds the install user.
install -d -m 0755 "$pkgdir/usr/share/sddm/themes"
cp -a default/sddm/omarchy "$pkgdir/usr/share/sddm/themes/"
find "$pkgdir/usr/share/sddm/themes/omarchy" -type d -exec chmod 0755 {} +
find "$pkgdir/usr/share/sddm/themes/omarchy" -type f -exec chmod 0644 {} +
install -Dm644 default/sddm/hyprland.lua "$pkgdir/usr/share/sddm/hyprland.lua"
install -Dm644 default/wayland-sessions/omarchy.desktop \
"$pkgdir/usr/local/share/wayland-sessions/omarchy.desktop"
# Plymouth theme. Files at 0644, dirs at 0755 (the upstream plymouth
# package's convention for /usr/share/plymouth/themes/*). cp -a inherits
# the source dir's mode, which is whatever the build host has — chmod
# explicitly so installs are consistent regardless of build environment.
install -d -m 0755 "$pkgdir/usr/share/plymouth/themes/omarchy"
cp -a default/plymouth/. "$pkgdir/usr/share/plymouth/themes/omarchy/"
find "$pkgdir/usr/share/plymouth/themes/omarchy" -type d -exec chmod 0755 {} +
find "$pkgdir/usr/share/plymouth/themes/omarchy" -type f -exec chmod 0644 {} +
# System font.
install -Dm644 default/fonts/omarchy/omarchy.ttf "$pkgdir/usr/share/fonts/omarchy/omarchy.ttf"
# systemd system-sleep hook (lazy-unmounts gvfsd-fuse mounts before
# suspend/hibernate). The script also ships under /usr/share/omarchy/default
# via the default/** copy above; we additionally install it to the live
# systemd path so the hook fires.
install -Dm755 default/systemd/system-sleep/unmount-fuse \
"$pkgdir/usr/lib/systemd/system-sleep/unmount-fuse"
# Branding assets (logos, icons).
install -Dm644 logo.txt "$pkgdir/usr/share/omarchy/logo.txt"
install -Dm644 logo.svg "$pkgdir/usr/share/omarchy/logo.svg"
install -Dm644 icon.txt "$pkgdir/usr/share/omarchy/icon.txt"
install -Dm644 icon.png "$pkgdir/usr/share/omarchy/icon.png"
# Standard icon-theme locations so os-release's LOGO=omarchy resolves in
# desktop/system-info tools that use the freedesktop icon lookup rules.
install -Dm644 icon.png "$pkgdir/usr/share/pixmaps/omarchy.png"
install -Dm644 icon.png "$pkgdir/usr/share/icons/hicolor/256x256/apps/omarchy.png"
# Seed the user-editable branding files into /etc/skel so fresh users
# have working defaults for `omarchy screensaver` and the About screen
# from the moment they're created. omarchy-reinstall-configs refreshes
# these from the /usr/share/omarchy/ sources for existing users.
install -Dm644 logo.txt "$pkgdir/etc/skel/.config/omarchy/branding/screensaver.txt"
install -Dm644 icon.txt "$pkgdir/etc/skel/.config/omarchy/branding/about.txt"
# Other static per-user defaults seeded via /etc/skel for new users.
# omarchy-finalize-user no longer copies these into $HOME; existing users
# resync via omarchy-reinstall-configs.
install -Dm644 default/hypr/toggles/flags.lua \
"$pkgdir/etc/skel/.local/state/omarchy/toggles/hypr/flags.lua"
install -Dm644 default/nautilus-python/extensions/localsend.py \
"$pkgdir/etc/skel/.local/share/nautilus-python/extensions/localsend.py"
install -Dm644 default/nautilus-python/extensions/transcode.py \
"$pkgdir/etc/skel/.local/share/nautilus-python/extensions/transcode.py"
# Tensaku asks for an annotation size on first run unless its persisted
# state already names one; seeding it keeps the first screenshot quiet.
install -Dm644 default/tensaku/state.toml \
"$pkgdir/etc/skel/.local/state/tensaku/state.toml"
# Support binaries needed before the full omarchy package is installed
# (used by ISO/recovery flows).
install -Dm755 bin/omarchy-upload-log "$pkgdir/usr/bin/omarchy-upload-log"
install -Dm755 bin/omarchy-debug "$pkgdir/usr/bin/omarchy-debug"
install -Dm755 bin/omarchy-debug-idle "$pkgdir/usr/bin/omarchy-debug-idle"
}