diff options
| -rw-r--r-- | .chezmoiignore | 1 | ||||
| -rw-r--r-- | .github/copilot-instructions.md | 5 | ||||
| -rwxr-xr-x | bootstrap.sh | 30 | ||||
| -rw-r--r-- | justfile | 54 | ||||
| -rw-r--r-- | systemd-units/base.txt | 13 |
5 files changed, 73 insertions, 30 deletions
diff --git a/.chezmoiignore b/.chezmoiignore index 2cde505..f6f6893 100644 --- a/.chezmoiignore +++ b/.chezmoiignore @@ -5,6 +5,7 @@ create-efi.sh .github/ .worktrees/ meta/ +systemd-units/ etc/ firefox/ justfile diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 2a837f5..44239ac 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -15,12 +15,13 @@ The repo root is a chezmoi source directory. Files targeting `$HOME` use chezmoi - `dot_config/`, `private_dot_gnupg/`, `private_dot_ssh/`, etc. — chezmoi source state mapping to `$HOME`. Prefix meanings: `dot_` → leading `.`, `private_` → restricted permissions, `executable_` → `+x` bit. - `etc/` contains system-level configs (`/etc/` targets) — systemd units, pacman hooks, sysctl tunables, kernel module loading. Deployed by `run_onchange_after_deploy-etc.sh.tmpl`. - `meta/` contains plain text package lists for Arch Linux (one package per line, `#` comments). Each `.txt` file represents a group (e.g. `base.txt`, `dev.txt`, `wayland.txt`). Install with `just install base dev` or `just install-all`. Detect drift with `just status`. +- `systemd-units/` contains plain text systemd unit lists paired by name with `meta/` groups (e.g. `systemd-units/base.txt` ↔ `meta/base.txt`). Units listed here are enabled by `just services-enable` (run automatically by `just init`). Inspect with `just services`, detect drift with `just services-drift`. - `firefox/` contains Firefox/LibreWolf hardening overrides (`user-overrides.js`) and custom CSS (`chrome/userChrome.css`). Deployed by `run_onchange_after_deploy-firefox.sh.tmpl`. - `dot_local/bin/executable_create-efi` is an interactive EFI boot entry creation script using `efibootmgr` (deployed to `~/.local/bin/create-efi`). - `bootstrap.sh` at the repo root is a POSIX shell script that takes a fresh minimal Arch install (only `base`) to a fully deployed state. It installs prerequisites, enables `%wheel` sudoers, bootstraps `paru-bin` from the AUR, clones the repo, runs `just init`, and optionally invokes `create-efi`. Designed to be curlable: `curl -fsSL .../bootstrap.sh | sh`. -- `.chezmoiignore` excludes non-home files (`etc/`, `meta/`, `firefox/`, docs) from deployment to `$HOME`. +- `.chezmoiignore` excludes non-home files (`etc/`, `meta/`, `systemd-units/`, `firefox/`, docs) from deployment to `$HOME`. - `.githooks/` contains git hooks (notably `post-commit` which runs `chezmoi apply`). Activated by `just init`. -- `justfile` provides recipes: `init` (first-time setup), `sync` (apply + fix), `apply`, `fix`, `status`, `pkg-drift`, `dotfile-drift`, `undeclared`, `diff`, `merge`, `groups`, `install`, `install-all`, `add`, `remove`. Run `just` or `just --list` to see them. +- `justfile` provides recipes: `init` (first-time setup), `sync` (apply + fix), `apply`, `fix`, `status`, `pkg-drift`, `dotfile-drift`, `undeclared`, `diff`, `merge`, `groups`, `install`, `install-all`, `add`, `remove`, `services`, `services-enable`, `services-drift`. Run `just` or `just --list` to see them. ## Window manager diff --git a/bootstrap.sh b/bootstrap.sh index c5cbb26..dbe9495 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -70,43 +70,19 @@ cd "$DOTFILES_DIR" log 'running just init' just init -# 6. enable recommended systemd units for daemons that base.txt installs. -# Soft-fail: warn on a single failure but keep going. -log 'enabling system services' -for u in \ - fstrim.timer \ - systemd-timesyncd.service \ - systemd-resolved.service \ - reflector.timer \ - paccache.timer \ - pkgstats.timer \ - acpid.service \ - cpupower.service \ - iwd.service -do - sudo systemctl enable --now "$u" \ - || warn "could not enable $u" -done - -# tlp: laptops only -if ls /sys/class/power_supply/BAT* >/dev/null 2>&1; then - sudo systemctl enable --now tlp.service \ - || warn 'could not enable tlp.service' -fi - -# 7. refresh pacman mirrorlist once via reflector (config deployed by chezmoi) +# 6. refresh pacman mirrorlist once via reflector (config deployed by chezmoi) log 'refreshing pacman mirrorlist via reflector' sudo reflector @/etc/xdg/reflector/reflector.conf \ --save /etc/pacman.d/mirrorlist \ || warn 'reflector failed; keeping existing mirrorlist' -# 8. create XDG user directories (~/Documents, ~/Downloads, etc.) +# 7. create XDG user directories (~/Documents, ~/Downloads, etc.) if command -v xdg-user-dirs-update >/dev/null 2>&1; then log 'creating XDG user directories' xdg-user-dirs-update || warn 'xdg-user-dirs-update failed' fi -# 9. optional: create an Arch EFI boot entry if none exists +# 8. optional: create an Arch EFI boot entry if none exists if [ -d /sys/firmware/efi ]; then if ! sudo efibootmgr 2>/dev/null | grep -iq arch; then log 'no Arch Linux EFI boot entry found; launching create-efi' @@ -8,7 +8,7 @@ default: # ═══════════════════════════════════════════════════════════════════ # First-time machine setup: regenerate chezmoi config, install git hooks, deploy dotfiles, install base packages -init: _chezmoi-init _install-hooks apply (install "base") +init: _chezmoi-init _install-hooks apply (install "base") services-enable # ═══════════════════════════════════════════════════════════════════ @@ -122,6 +122,58 @@ groups group="": # ═══════════════════════════════════════════════════════════════════ +# Services +# ═══════════════════════════════════════════════════════════════════ + +# List curated systemd units (grouped by systemd-units/<group>.txt) with state +services: + #!/bin/sh + for file in systemd-units/*.txt; do + [ -f "$file" ] || continue + group=$(basename "$file" .txt) + echo "=== $group ===" + grep -v '^\s*#' "$file" | grep -v '^\s*$' | while read -r u; do + en=$(systemctl is-enabled "$u" 2>/dev/null); en=${en:-unknown} + ac=$(systemctl is-active "$u" 2>/dev/null); ac=${ac:-unknown} + case "$en" in + enabled|static|alias) c_en=32 ;; + disabled|masked|not-found) c_en=31 ;; + *) c_en=33 ;; + esac + case "$ac" in + active) c_ac=32 ;; + inactive|failed) c_ac=31 ;; + *) c_ac=33 ;; + esac + printf ' %-34s \033[%sm%-10s\033[0m \033[%sm%s\033[0m\n' "$u" "$c_en" "$en" "$c_ac" "$ac" + done + done + +# Enable all curated systemd units (idempotent, soft-fail per unit) +services-enable: + #!/bin/sh + for file in systemd-units/*.txt; do + [ -f "$file" ] || continue + grep -v '^\s*#' "$file" | grep -v '^\s*$' | while read -r u; do + sudo systemctl enable --now "$u" \ + || echo " warn: could not enable $u" >&2 + done + done + +# Show drift between curated services and actually-enabled services +services-drift: + #!/bin/sh + echo "=== Service drift ===" + tmp=$(mktemp -d); trap 'rm -rf "$tmp"' EXIT + cat systemd-units/*.txt 2>/dev/null \ + | grep -v '^\s*#' | grep -v '^\s*$' | sort -u > "$tmp/curated" + systemctl list-unit-files --state=enabled --no-legend 2>/dev/null \ + | awk '{print $1}' | sort -u > "$tmp/enabled" + comm -23 "$tmp/curated" "$tmp/enabled" | sed 's/^/ not-enabled: /' + comm -13 "$tmp/curated" "$tmp/enabled" | sed 's/^/ uncurated: /' + + +# ═══════════════════════════════════════════════════════════════════ # Package management # ═══════════════════════════════════════════════════════════════════ diff --git a/systemd-units/base.txt b/systemd-units/base.txt new file mode 100644 index 0000000..bec3556 --- /dev/null +++ b/systemd-units/base.txt @@ -0,0 +1,13 @@ +# Systemd units to enable when the 'base' meta group is installed. +# One unit per line, # comments OK. + +fstrim.timer +systemd-timesyncd.service +systemd-resolved.service +reflector.timer +paccache.timer +pkgstats.timer +acpid.service +cpupower.service +iwd.service +tlp.service |
