flowchart TD
A[Package audit] --> F[Unmanaged package found]
F --> Q{Is the package needed?}
Q -->|No / not intentional| R[Remove package]
Q -->|Yes, for the lab baseline| M["<a href='https://github.com/fs-ise/workstation-setup/tree/main/roles' target=_blank>Add to shared role</a>"]
Q -->|Yes, managed personally| O[Add to overlay role]
Q -->|Yes, genuine local exception| L[Add narrow exception in topmost layer]
M --> DS[Repository desired state updated]
O --> DS
L --> DS
R --> C[Local drift removed]
DS --> U[Run make install again]
U --> W[Workstation aligned]
Update software
Use this page to update installed software and keep an existing workstation aligned with this repository. Fedora and Flatpak update software from their configured repositories, Ansible reapplies the desired state used during Install software, and the package audit detects unmanaged software or drift.
Routine update workflow
On a shared-only workstation, run the complete update and audit from this repository:
make updateThis target stops immediately if a step fails. Its Git behavior depends on the kind of checkout:
- Branch checkout:
make updaterunsgit pull --ff-onlybefore updating the workstation. Divergent local history is not merged automatically. - Tagged or other detached checkout:
make updateskips the Git pull and prints a notice. It preserves the selected configuration snapshot while still refreshing dependencies, updating Fedora and Flatpak software, reapplying the stack, and running the audit. It does not switch branches or select a newer tag.
It then runs the following underlying commands in order; use them individually for troubleshooting:
# On a branch only; skipped on a tagged or other detached checkout
git pull --ff-only
# Install or refresh the repository's pinned Ansible Galaxy collections
make deps
# Update Fedora packages
sudo dnf upgrade --refresh
# Update Flatpak applications
flatpak update
# Reapply the managed workstation configuration
make install
# Underlying command: ansible-playbook -i inventory -K playbooks/lab-stack.yml
# Audit DNF packages and manual filesystem installations
make audit
# Underlying command: ansible-playbook -i inventory -K playbooks/audit-unmanaged-packages.ymlThe commands intentionally run in this order:
- On a branch, update the setup repository with a fast-forward-only pull. On a tagged or other detached checkout, keep the selected Git snapshot unchanged.
- Install or refresh the Ansible Galaxy dependencies declared in
requirements.yml. Collection versions are intentionally pinned so tagged releases use the same tested dependencies on every workstation. - Update Fedora packages and Flatpak applications from their configured repositories. These commands omit
-yso you can review consequential changes before installation. - Reapply the Ansible desired state after the software updates.
- Audit the resulting system for DNF package drift and high-signal manual filesystem installations.
ansible-playbook is not a substitute for dnf upgrade or flatpak update. Most roles ensure that selected packages are present and configured; they do not generally upgrade every installed package.
make update delegates the update and configuration steps to make update-base, then runs make audit. A personal overlay calls update-base, applies its own roles, and owns the final combined audit. This keeps the shared workflow composable without making it depend on any overlay.
The audit reports two kinds of unmanaged software:
- A DNF User-reason but Ansible-unmanaged package is tracked by RPM/DNF with the install reason
User, but is not declared in this repository’s managed package lists or package allowlists. Packages withGroupor dependency-related reasons are excluded.External Userand other external or uncertain reasons are reported separately for review but do not fail the audit. If DNF5 reason reporting is unavailable, the audit preserves compatibility by treating the older command’s--userinstalledresults as user-requested. - An unmanaged filesystem installation is a file, symlink, or
/optinstallation that is not owned by an RPM and is not in the separate manual-install allowlists. This commonly includes software unpacked from tarballs.
The DNF managed set has no separate package manifest. The audit discovers roles/*/defaults/main.yml, loads those role defaults, and combines every <role>_managed_dnf_packages declaration, then trims, deduplicates, and sorts package names before comparing them. When a role adds a DNF package, declare it in that role’s package variables and expose it through <role>_managed_dnf_packages; use the same variable from the install task where practical. The audit therefore follows the installation source of truth instead of copying package names into group_vars.
Audit unmanaged packages
Local package changes should not remain invisible. The audit helps identify software that was installed manually or introduced outside the Ansible-managed package lists.
For each audit finding, decide what it means:
- Unintentional change or unnecessary software: remove the package.
- Software needed on all managed workstations: add it to the relevant Ansible role.
- Software managed by a personal or other overlay: declare it in that overlay’s role package list and run the combined audit from the overlay.
- A genuine local exception: record a narrow exception in the topmost configuration layer. Do not add personal packages to the shared allowlist.
AI coding tools such as ChatGPT or Codex can help draft the required Ansible changes, but review package names, repository additions, and role placement before committing.
Decision workflow
How filtering works
To keep the audit actionable, this repository supports two filtering mechanisms:
package_audit_allowlistfor exact package namespackage_audit_allowlist_patternsfor regex-based package families
Use exact allowlist entries whenever possible. The shared allowlist is reserved for shared Fedora/system exceptions; overlay exceptions belong in the overlay. Regex patterns are reserved for tightly bounded package families, such as known kernel subpackages.
Every pattern must enumerate the allowed suffixes and match the complete package name. Do not use open-ended prefixes such as ^lib, ^perl, or ^gnome-: they can hide unrelated software that a user installed manually.
Audit manual filesystem installations
The filesystem category checks regular files and symlinks in /usr/local/bin and /usr/local/sbin, plus direct directory and symlink children of /opt. It resolves executable symlinks where possible and asks RPM which package owns the effective path. RPM-owned entries are not findings, and broken symlinks are reported safely. The audit intentionally does not scan ~/.local, where tools such as uv, pipx, Cargo, and npm commonly create legitimate user-managed files.
Configure this category independently in group_vars/all/package_audit.yml:
manual_install_audit_allowlist:
- local-tool
- /opt/institution-tool
manual_install_audit_allowlist_patterns:
- '^lab-'
manual_install_audit_fail_on_unmanaged: false
manual_install_audit_recommendations:
quarto: "Install the official Quarto RPM through the quarto role."Exact and regex allowlists match either the normalized installation name or its reported path. Prefer exact entries and keep patterns narrow. The default is report-only; set manual_install_audit_fail_on_unmanaged to true to make remaining findings fail the playbook.
Prefer a suitable official RPM or package-managed installation over a tarball/manual installation. Allowlist intentional exceptions rather than deleting them: this audit is read-only and never changes detected software.