- Use samba/openssh package names on Arch instead of Debian-style samba-client/openssh-server
- Skip AUR-only freeipa install when ipa-client-install already present; skip oddjob if not in official repos
- Guard seed_policystore delegate_to when ipa_server_host is undefined
- Make hostname detection and OS version parsing more robust
- Fix inverted DNS_UPDATE/CONFIGURE_SUDO enrollment flags
The 1550-line ansipa-enforce-policies.sh is replaced by a slim orchestrator
that sources policy files from policies.d/ — one file per policy type — via
a shared lib/ansipa-policy.sh that consolidates all IPA group discovery into
two queries (one host-show, one group-find) instead of five or more.
New files:
- ansible/lib/ansipa-policy.sh shared constants, log/warn, _ansipa_discover(),
_smb_parse_cred(), _ansipa_sync_policystore()
- ansible/policies.d/dev_daemon.sh
- ansible/policies.d/dev_timeshift-backup.sh
- ansible/policies.d/dev_security-scan.sh
- ansible/policies.d/dev_no-local-users.sh
- ansible/policies.d/dev_local-sudo.sh
- ansible/policies.d/dev_ssh.sh
- ansible/policies.d/dev_mon.sh includes usr_mon_logins (same CMK dep)
- ansible/policies.d/usr_admin.sh
- ansible/policies.d/usr_block-binary.sh
- ansible/policies.d/usr_prt.sh
- ansible/policies.d/usr_scan-notify.sh
- ansible/policies.d/usr_smb.sh
- ansible/policies.d/usr_policystore.sh NEW: auto-mount ~/policystore for
usr_smb_adm_policystore members
The policies.d/ folder on the FreeIPA container is exposed as an SMB share
(ansipa-policystore) so admins can live-edit policy files without Ansible.
The enforcer syncs from the share before each run; cached local files are
used as fallback when SMB is unreachable.
- ansipa-smb-setup.sh: adds ansipa-policystore share + smb-policystore system
user + usr_smb_adm_policystore IPA group with auto-generated credential
- deploy-ansipa-policies.yml: deploys lib/ and policies.d/ to enrolled clients;
adds optional seed_policystore task for bootstrap
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ansipa-enforce-policies.sh header: add missing dev_ssh_*, usr_smb_r_*,
usr_smb_rw_*, dev_mon_* (base/malware/timeshift/power), usr_mon_logins
with concise descriptions matching actual behaviour. Notes section
updated with CheckMK setup prerequisite.
- ansipa_packages local check: replace broken rpm||dpkg fallback (wc -l
always exits 0 so dpkg/pacman branches were never reached) with an
if/elif/elif that probes for rpm, dpkg, or pacman in order. Includes
pacman.log-based recent-packages list for Arch hosts.
- deploy-ansipa-policies.yml prerequisites: add CheckMK and SMB mount notes.
- .env.example: add CheckMK section (CMK_ADMIN_PASSWORD, CMK_SITE_ID).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds full CheckMK CE 2.3 monitoring integration to the ansipa policy
enforcement system. Monitoring is group-driven — adding a host to an
IPA hostgroup installs the relevant agent checks automatically.
New monitoring groups:
dev_mon_base — install check-mk-agent, register host in CMK;
packages check + built-in CPU/RAM/disk/uptime
dev_mon_malware — ClamAV scan results from dev_security-scan log
dev_mon_timeshift — Timeshift snapshot age (WARN >5d, CRIT >10d)
dev_mon_power — CPU package TDP via Intel RAPL or lm-sensors
usr_mon_logins — SSH login attempts (success/failed/invalid-user)
Key implementation details:
- ansipa-checkmk-setup.sh: one-time folder/group creation on FreeIPA
container; reads automation secret from shared cmk-creds volume;
stores credentials in IPA dev_mon_base description for clients
- ansipa-checkmk.service: starts after IPA first-boot, retries until
both IPA and CheckMK are ready
- docker-compose.yml: CheckMK container adds port 8000 (agent receiver
for push mode); command override writes automation.secret to shared
volume, patches cookie_auth.conf for API access, and polls
/cmk-creds/push-mode-*.req to configure push-agent hosts in hosts.mk
- ansipa-enforce-policies.sh: local check scripts for all 5 groups;
cmk-agent-ctl registration + auto push timer when push mode is active
- CheckMK REST API path corrected to /cmk/check_mk/api/1.0/ (not
/cmk/api/1.0/ which returns 404 in 2.3)
- .gitignore added to prevent accidental commit of .env test creds
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DHops6PU4c2Mv5UyhUj8Ms
usr_smb_r_<name> / usr_smb_rw_<name> (user groups):
- Server creates /data/smb-shares/<name>/ with smb-<name> system user,
setgid directory, and Samba share stanzas [usr-<name>-r/rw] on startup
- Auto-generates credentials and stores them in IPA group descriptions
(cifs://<host>:<samba-user>:<password>) so no out-of-band secret distribution
- Client mounts //ipa/<share> at ~/‹name› for logged-in members;
rw membership wins over r when user is in both groups
- Revert: unmounts and rmdir the mount point on group leave
dev_ssh_<userid> (host group):
- Reads IPA user's SSH public keys (ipasshpubkey / --all output)
- Writes them into /home/<userid>/.ssh/authorized_keys in an
ansipa-managed section (preserves manually-added keys)
- Home dir is created if it doesn't exist (user may not have logged in yet)
- Revert: removes only the ansipa-managed section on group leave
- Enables same-key SSH access from any registered device to enrolled hosts
Also: add cifs-utils + openssh-server to Ansible package list
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DHops6PU4c2Mv5UyhUj8Ms
Three bugs fixed, all confirmed end-to-end in a live FreeIPA + client VM:
1. Wrong `who` column: loginctl is SESSION/UID/USER (col 3), but `who` is
USER/TTY/DATE (col 1) — the fallback used col 3, delivering to the wrong
user. Split into _parse_session_user() with per-source column selection.
2. Delivered to all users: alerts were sent to every active non-root session
instead of only members of usr_scan-notify. Added `id -nG` group check
inside _parse_session_user().
3. smbclient ls path breakage: `smbclient -c "ls alerts\host\"` treats the
argument as a glob pattern, returning NT_STATUS_NO_SUCH_FILE. Changed to
`cd alerts\host; ls` which correctly lists directory contents.
Bonus: track ACKNOWLEDGED set so alerts deleted-from-server in the current
run are not re-downloaded (avoiding a spurious WARN on the same run).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DHops6PU4c2Mv5UyhUj8Ms
Fixes found during a complete archiso → FreeIPA DC → client enrollment →
ansipa policy deployment test cycle (Rocky 9 client VM, FreeIPA in Docker):
arch-autoinstall.sh:
- Add openssh to pacstrap — was missing, breaking headless/automated installs
- Enable sshd at boot and set PermitRootLogin yes for post-install access
ansipa-install-packages.sh:
- Fix broken uninstall logic: three always-true conditions caused every package
removal to be silently skipped; replace with a state-file-based approach that
tracks packages installed by ansipa and removes only those when the IPA group
disappears
ansipa-enforce-policies.sh:
- Add usr_admin policy: creates /etc/sudoers.d/ansipa-usr-admin granting full
sudo to the FreeIPA usr_admin user group on every enrolled host; reverted
when the IPA group is deleted
- Add usr_prt_<printer> policy: auto-adds CUPS printers for FreeIPA user group
members at login; printer URI stored in IPA group description; per-user ACL;
reverted when group is deleted or membership ends
deploy-ansipa-policies.yml:
- Document usr_admin and usr_prt_* policies in header comment
- Install cups package on clients (required for printer policy)
FreeIPA container (image/):
- Add docker-env.service: extracts IPA_*/SMB_*/LUKS_*/KEYCLOAK_* env vars from
/proc/1/environ into /etc/container.env on container start; services read from
there rather than relying on PassEnvironment (which is lost on container restart)
- Add run.sh: wrapper that starts FreeIPA with --cgroupns host, required on cgroup
v2 hosts (WSL2, recent Linux) because Docker Compose schema does not expose
cgroupns_mode; also wires LUKS_KEY_UPLOAD_PASSWORD which the SMB service needs
- Dockerfile: copy + enable docker-env.service; add glibc-langpack-en for locale
- ansipa-smb.service: use EnvironmentFile=/etc/container.env (via docker-env.service)
instead of PassEnvironment; add docker-env.service dependency
- ipa-first-boot.service: add docker-env.service dependency + EnvironmentFile
- ipa-first-boot.sh: add --skip-mem-check (container has limited cgroup memory
visibility); remove --no-reverse from non-DNS path (was invalid without DNS)
- docker-compose.yml: add prominent cgroupns note explaining when to use run.sh
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DHops6PU4c2Mv5UyhUj8Ms
Same Vicinae theming bug as hyprlua, now fixed across the remaining DE modules:
- Vicinae loads named custom themes only from ~/.local/share/vicinae/themes/*.toml,
not ~/.config/vicinae/. Both modules now deploy cyberqueer.toml there so
settings.json's theme.dark.name="cyberqueer" resolves instead of falling back
to the stock dark theme.
- hyprland: the source had settings.json double-nested at vicinae/vicinae/, so it
deployed to ~/.config/vicinae/vicinae/settings.json and was never read. Flattened
the source to vicinae/{settings.json,cyberqueer.toml} (matching hyprlua), so it
now lands at ~/.config/vicinae/settings.json.
- niri/vicinae is a symlink to hyprlua/vicinae and niri.sh uses `cp -rL`, so its
settings.json was already correct; only the theme-deploy line was needed.
Verified by simulating both deploys into a temp HOME: final layout matches the
known-good hyprlua result.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R5kHioUMK3mtf2eiLEozCM
The config-copy step put cyberqueer.toml into ~/.config/vicinae/, but Vicinae
loads NAMED custom themes only from ~/.local/share/vicinae/themes/*.toml (per
the official docs). So settings.json's theme.dark.name="cyberqueer" never
resolved and the launcher silently fell back to the stock dark theme.
Copy the theme into ~/.local/share/vicinae/themes/ so the named theme resolves
and the cyberqueer palette is applied.
Note: the hyprland and niri DE modules have separate, pre-existing Vicinae
layout issues (hyprland double-nests settings.json; niri bundles no vicinae
config) — left for a dedicated follow-up.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R5kHioUMK3mtf2eiLEozCM
core-packages installs ffmpeg, which depends on the virtual `jack`. With only
`pipewire` (not pipewire-jack) requested, pacman --noconfirm picks the default
provider `jack2`. The DE modules then install `pipewire-jack`, which conflicts
with the already-installed jack2 — pacman can't auto-resolve it and aborts the
whole DE module ("pipewire-jack and jack2 are in conflict").
Explicitly list pipewire-jack/pipewire-pulse/pipewire-alsa in core-packages so
PipeWire is the chosen provider from the start; jack2 is never pulled and the DE
package install no longer conflicts.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R5kHioUMK3mtf2eiLEozCM
Two more module aborts surfaced by the live VM test (both pre-existing, only
unmasked once the wprs bug was fixed and the transaction got further):
1. core-packages.sh listed BOTH `rust` and `rustup`. They conflict (both provide
cargo/rustc); pacman --noconfirm cannot auto-resolve it and aborts the whole
core-packages transaction ("unresolvable package conflicts"), so wget and the
other core tools never installed. Drop `rust` — the setup uses rustup
exclusively (`rustup default stable`).
2. core.sh copied the greetd config into /etc/greetd before that directory
existed (greetd is pulled in later by the DE module), so the cp failed and
`set -e` aborted Core Services before fail2ban/udisks2 were enabled. mkdir -p
/etc/greetd first.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R5kHioUMK3mtf2eiLEozCM
Live VM test revealed the HyprLua DE install aborted at the cursor-download step
("wget: command not found", exit 127), leaving ~/.config/hypr undeployed. Two
root causes:
1. core-packages.sh listed `wprs` in the pacman array, but wprs is AUR-only
(wprs-git). pacman aborts the ENTIRE transaction on an unknown target, so the
whole core-packages install failed with "target not found: wprs" — and NONE
of the core packages installed, including wget. Removed wprs (it has its own
optional wprs.sh AUR module) and documented why it must never be re-added.
2. hyprlua/hyprland/niri downloaded the cursor theme and wallpaper with wget,
which is not part of the base system. Switched them to curl (always present),
so the DE install no longer depends on an earlier module having installed wget.
Without these, HyprLua silently half-installed (packages yes, config no) and the
booted system had no Hyprland configuration.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R5kHioUMK3mtf2eiLEozCM
A bare `chsh -s /usr/bin/zsh` authenticates the calling user through PAM and
prompts "Password:", stalling an unattended install right after oh-my-zsh.
Run it via `sudo chsh ... "$(whoami)"` so it uses the passwordless setup sudo
rule and completes silently (also more reliable: it targets the account
explicitly rather than relying on the ambient user).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R5kHioUMK3mtf2eiLEozCM
oh-my-zsh's install script, even with RUNZSH=no/CHSH=no, still prompts
"Do you want to overwrite it with the Oh My Zsh template? [Y/n]" in interactive
mode — which hangs an unattended/answerfile install at the shell-setup module.
Pass --unattended to skip all prompts, and KEEP_ZSHRC=yes so it preserves the
dotfiles ~/.zshrc symlink (created earlier in this module) instead of replacing
it with the oh-my-zsh template.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R5kHioUMK3mtf2eiLEozCM
Audited every module for prompts that would hang an answerfile/unattended run.
The EWW form-factor question and several interactive-config modules were still
unguarded (only hyprlua had been fixed):
- hyprland.sh, niri.sh: skip the EWW form-factor `read` when MARCHY_UNATTENDED=1
or stdin is not a TTY, defaulting to the desktop/no-battery bar (matches hyprlua).
- mail-notmuch.sh, caldav-sync.sh: install the tools, then exit cleanly in
unattended mode instead of blocking on the account/server credential prompts —
the user configures the account after first boot.
- freeipa-server.sh: bail out early in unattended mode; FreeIPA server provisioning
is interactive and must run on a booted system (ipa-server-install needs running
services), so it can never run during the install.
freeipa-client.sh is left as-is: it has a genuine --unattended enrolment path.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R5kHioUMK3mtf2eiLEozCM
An answerfile/PXE install runs the TUI modules with no operator present, so any
interactive prompt or confirmation hangs the deployment forever.
- tui-install.sh: run each module in the FOREGROUND with a background `tail -f`
mirroring its log, instead of backgrounding the module. Backgrounding made
interactive module reads (e.g. the EWW form-factor question) trigger SIGTTIN
and stop; the file-based log still avoids the `| tee` pipe-inherit hang that
paused installs after a module spawned a daemon. Export MARCHY_UNATTENDED=1
in answerfile mode so modules can detect it.
- hyprlua.sh: skip the EWW form-factor `read` when MARCHY_UNATTENDED=1 or stdin
is not a TTY, defaulting to the desktop/no-battery bar; add --noconfirm to the
tablet-branch yay call.
- python.sh: add --noconfirm --needed to its `pacman -Syu` so it no longer waits
on the "Proceed?" prompt during unattended installs.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R5kHioUMK3mtf2eiLEozCM
When the TUI modules run inside the archiso installer chroot, the new
system's systemd is not the running init and there is no user session bus.
Operations like `systemctl start`, `enable --now`, `systemctl --user`, and
`gsettings` fail there and, under `set -e`, abort the whole module.
- logging.sh: add in_chroot/have_user_bus/enable_service/start_service
helpers. enable_service warns instead of aborting; start_service skips in
a chroot (unit starts on first boot via its enable symlink).
- core.sh, hyprland.sh, hyprlua.sh, niri.sh: route enables through
enable_service, starts through start_service, and guard gsettings behind
have_user_bus. Fixes the cronie-enable failure and the ly/DM setup abort.
- app modules (tlp, timeshift, open-webui, mysql, qemu, ollama, cockpit,
docker, ssh-server): convert `enable --now`/plain enables to
enable_service + start_service so they no longer abort during chroot install.
- tui-install.sh: run modules with output to a file plus a pid-bound tail,
waiting on the module PID, so a daemon child inheriting the pipe can no
longer hang the installer after a module (e.g. flatpak) finishes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R5kHioUMK3mtf2eiLEozCM
- Flatpaks now install globally again: ensure_flatpak adds the Flathub remote at
--system and all 19 app modules use `sudo flatpak install --system`. Running
via sudo (root) performs the system op directly, avoiding the SystemHelper/
polkit D-Bus path that caused "The name is not activatable" for non-root users.
- tui-install.sh no longer prompts for or sets the hostname — the base installer
already configures it. Removed the Hostname section, the MAC-suffix helper, the
AF_HOSTNAME field and the summary line.
- archbaseos-guided-install.sh now gathers ALL input up front, including
passwords. New ask_password() prompts in clear text (by request) and requires a
confirmation entry, looping until the two match — so each password is typed
exactly twice and never again. The LUKS passphrase is captured once and fed to
luksFormat/open/luksAddKey (--key-file=-) and cryptenroll ($PASSWORD), instead
of cryptsetup prompting repeatedly. After all input, a single all-caps "type
YES" gate replaces the old per-step confirmations (answerfile mode keeps its
5-second abort window). The run-TUI choice is also asked up front.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diagnosed from a full guided-install log plus a Hyprland startup log. Three
distinct remaining failures:
1. ~/.config left root-owned. The FIDO/Yubico setup runs `mkdir -p
~/.config/Yubico` as root (creating ~/.config itself), then chowned only
Yubico/. ~/.config stayed root-owned, so every later user step failed with
EACCES: shell-setup symlinks (starship.toml), the mail/caldav systemd --user
timers, and Hyprland creating ~/.config/hypr at startup. Chown the whole
~/.config in both Yubico spots, and defensively reclaim it in shell-setup.
2. python/wprs/plymouth/zfs sourced ../lib/logging.sh, but apps/ modules need
../../lib — so they aborted with "No such file or directory". Corrected.
3. Flatpak app modules ran `flatpak install -y` at system scope, which needs the
Flatpak SystemHelper D-Bus service + polkit (unavailable in a chroot/TTY
install) — the "The name is not activatable" failures (wireshark, xournal,
rnote, firefox-browser, …). Switch ensure_flatpak and all 19 main-flow
installs to --user scope, matching apply_flatpak_theme's --user overrides.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The core, hyprlua and hyprland package installs used backslash-continued
`pacman` commands with inline `#` comments. Bash treats the first inline
comment as the end of the command, so pacman ran with only the packages
before it and every later name (7zip, cronie, nwg-dock-hyprland, …) was
executed as a shell command — failing under `set -e`. Move all three lists
into arrays, where per-item comments are valid, and install with `--`.
Also:
- himalaya: install the official `himalaya` package (AUR `himalaya-bin` is gone).
- mail-notmuch / caldav-sync: make the systemd *user* timer setup and the
initial sync best-effort. A bare TTY/chroot install has no user session bus
(and ~/.config may not be writable yet), so `systemctl --user` and the mkdir
could abort the module; warn and continue instead.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
opendeck is not in the official repos, so install the native AUR package
with yay (matching the repo's other AUR modules) and drop the Flatpak
path. Wire `opendeck` into Hyprland autostart instead of
`flatpak run com.mairtech.OpenDeck`, and update the idempotency guard.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
apps/ is for modules that install software during setup. freeipa-image is
support tooling for the ansipa controller, run manually before installation,
so it has no place in the TUI module picker.
- git mv optional-Modules/plymouth.sh → apps/plymouth.sh
- git mv apps/freeipa-image.sh → setup/tools/freeipa-image.sh
- modules.conf: add plymouth (default=on, excludes=plymouth-custom); remove freeipa-image
- generate-modules.sh: regenerate all sentinel regions (81 → 81 active modules,
freeipa-image dropped from checklist/summary/dispatch, plymouth added with on default,
conflict block gains plymouth ↔ plymouth-custom pair)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Installs io.github.suchnsuch.Tangent via Flatpak with cyberqueer theme
applied. Registered in TUI installer, answerfile generator, and docs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Installs md.obsidian.Obsidian via Flatpak with cyberqueer theme applied.
Registered in TUI installer, answerfile generator, and docs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Installs com.github.flxzt.rnote via Flatpak with cyberqueer theme
applied. Registered in TUI installer, answerfile generator, and docs
alongside xournal++ in the Productivity section.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Installs ydotool via pacman and OpenDeck via Flatpak, wires ydotoold
and OpenDeck into the Hyprland autostart. Registers the module in the
TUI installer, answerfile generator, and docs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- plymouth.sh: accepts PLYMOUTH_LOGO_SRC env var; PNG used as-is, SVG
converted via rsvg-convert (librsvg only installed when needed)
- apps/plymouth-custom.sh: thin wrapper that validates the caller-supplied
path and delegates to plymouth.sh with PLYMOUTH_LOGO_SRC exported
- install-modules.sh: adds 'Plymouth (custom)' checklist entry; prompts
for image path via inputbox before the confirmation dialog; exports
PLYMOUTH_LOGO_SRC into the module run
- generate-answerfile.sh: adds 'plymouth' (on by default) to the
components checklist to match tui-install.sh
- docs: installation.md and modules.md updated with Plymouth component,
answerfile schema, mkinitcpio note, and custom-logo module entry
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SyBNiWy3wpawrWb9ryVk7p
Move the splash logo into resources/bg-skull.svg so it's tracked in git
and always available alongside the dotfiles. build.sh now copies
resources/ into /root/installer/resources/ on the ISO. The Plymouth
module resolves the SVG from the repo copy first, ISO copy second —
no user intervention or ~/Pictures setup required.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SyBNiWy3wpawrWb9ryVk7p
Installs a custom Plymouth theme (m-archy) with bg-skull.svg converted
to PNG (Plymouth is PNG-only via libpng — no SVG support) and a 12-dot
magenta spinner animation. Enabled by default in tui-install.sh; also
available as an optional module in install-modules.sh. Archiso image
remains Plymouth-free.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SyBNiWy3wpawrWb9ryVk7p
Policy change: graphical apps now prefer Flatpak > pacman > AUR. Non-graphical
tools keep pacman > AUR > source. This makes installed apps sandboxed, keeps
system packages clean, and gives us a single hook point (apply_flatpak_theme)
to theme every GUI app consistently.
lib/logging.sh — two new helper functions sourced by every module:
ensure_flatpak()
Checks if flatpak is installed (pacman installs it if not) and ensures the
Flathub remote is registered. Called at the top of every Flatpak script so
the module is self-contained and safe to run in any order.
apply_flatpak_theme(app_id)
Copies gtk-themes/cyberqueer/ from the Dotfiles repo into ~/.themes/, then
calls `flatpak override --user --filesystem=~/.themes:ro <id>` so the
sandbox can read it, and `flatpak override --user --env=GTK_THEME=cyberqueer
<id>` to activate it. Gracefully skips with a warning if the theme source
directory is absent.
App scripts converted (pacman/AUR → Flatpak + theme):
ardour org.ardour.Ardour
audacity org.audacityteam.Audacity
chromium org.chromium.Chromium
firefox org.mozilla.firefox
geany org.geany.Geany
gimp org.gimp.GIMP
inkscape org.inkscape.Inkscape
kate org.kde.kate
kdenlive org.kde.kdenlive
krita org.kde.krita
librewolf io.gitlab.librewolf-community.librewolf
lmms io.lmms.LMMS
localsend org.localsend.localsend
min-browser com.github.minbrowser.min
mixxx org.mixxx.Mixxx
onlyoffice org.onlyoffice.desktopeditors
openshot org.openshot.OpenShot
rdp-client org.remmina.Remmina (was pacman remmina + freerdp + libvncserver;
Flatpak bundles all protocols, including VNC and SSH tunnels)
shotcut org.shotcut.Shotcut
steam com.valvesoftware.Steam
vscodium com.vscodium.codium
wireshark org.wireshark.Wireshark
xournal com.github.xournalpp.xournalpp
zed dev.zed.Zed
zen-browser io.github.zen_browser.zen
Special cases:
blender-povray: Blender → Flatpak (org.blender.Blender) + theme; POV-Ray
stays pacman because it has no Flatpak and is a CLI renderer, not a GUI app.
prismlauncher / stuntrally: were already Flatpak installs; added
apply_flatpak_theme so they pick up the cyberqueer theme like everything else.
vesktop: switched from AUR vesktop to Flatpak dev.vencord.Vesktop. The AUR
build requires cargo and takes several minutes; the Flatpak is pre-built.
Vencord config is now deployed to ~/.var/app/dev.vencord.Vesktop/config/
(both Vencord/ and vesktop/ sub-dirs) instead of ~/.config/, which is where
the Flatpak sandbox exposes its config directory.
k8s: kubectl stays pacman (it is a CLI tool with no GUI, no Flatpak needed);
podman-desktop switches from pacman podman-desktop to Flatpak
io.podman_desktop.PodmanDesktop + theme, because it is a full GUI app.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add presence-detect.sh daemon: checks webcam every 2 min via OpenCV haar
cascade (presence_detect.py); holds systemd-inhibit --what=idle lock while a
face is detected so hypridle never fires during an active session
- Add enroll-biometrics.sh: Cyberqueer dialog TUI for camera configuration/test
and howdy face auth enrollment (add/list/remove/test models)
- Rewrite caffeine.sh (hyprlua + niri): replace kill/restart of idle daemon with
systemd-inhibit --what=idle:sleep + PID file; idle daemon stays running
- Fix hypridle.conf: correct ;; → ; in after_sleep_cmd, add
ignore_dbus_inhibit=false, bump lock timeout 120s→180s to account for the
2-min presence detection cycle
- Wire Super+Shift+B keybind for enrollment TUI in both hyprlua and niri
- Fix niri/scripts/python: was real dir with inner symlink causing cp -rL to
create a nested python/python/ hierarchy; replaced with direct symlink
- Add python-opencv and v4l-utils to hyprlua + niri installers
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reverts incorrect touch_long_press_time option (not a real Hyprland setting).
Adds evdev-right-click-emulation install + systemd enable to the tablet (T)
eww bar selection in the hyprlua installer.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds w3m to the install list and appends the text/html mailcap entry
so alot renders HTML emails as plain text via w3m -dump.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The glob path = .../calendars/* was not expanded by khal, so no events
were visible. Now caldav-sync.sh and ics-to-calendarim both generate
explicit [[name]]/path entries per calendar and regenerate the config
on every sync so newly discovered calendars are picked up automatically.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Installs vdirsyncer + khal, writes vdirsyncer/khal configs, creates
ics-to-calendarim converter to populate calendar.vim local JSON cache,
and sets up a systemd user timer for 15-minute periodic sync.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- x now opens a full-screen overlay: alot left (55%), abook top-right,
calendar bottom-right
- Add esc = exit bindings to alot config for search/thread/taglist/
bufferlist modes, applied to live ~/.config/alot/config and to the
mail-notmuch.sh setup script
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace tab/vsplit PIM approach with nvim_open_win floating windows:
r opens a tiled full-screen overlay (alot top, calendar+abook bottom)
n/g/f open individual centered floats with rounded border
- Add setup/modules/optional-Modules/apps/mail-notmuch.sh:
configures mbsync, msmtp, notmuch, alot from interactive prompts
installs a systemd user timer for 5-min periodic mail sync
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Pin pamu2fcfg enrollment to the target hostname (-o/-i pam://$HOSTNAME)
so the credential origin matches pam_u2f.so at runtime; enrolling outside
the chroot previously used the live ISO hostname, causing auth to fail
- Add `cue` to the pam_u2f.so PAM line so ly prompts the user to touch
the key after password entry
- Add --needed to hyprlua AUR yay call to survive re-runs
- Degrade gracefully in lamco-rdp-server when no user D-Bus session is
active (systemctl --user enable would abort the module under set -e)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add modules/lib/logging.sh with log(), skip(), warn(), err() helpers.
Source it in all 84 scripts (core, DEs, optional apps) and replace bare
echo calls with structured log messages. Add log file capture to install.sh.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
sauerbraten: open-source Cube 2 FPS (pacman)
stuntrally: rally racing game via Flatpak (io.github.stuntrally.StuntRally3)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
openarena: open-source Quake III Arena (pacman)
tetris: bastet + vitetris (pacman + AUR)
doom: Chocolate Doom + Freedoom game data (pacman)
Wired up in simple-install.sh, tui-install.sh, and install-modules.sh.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>