A collection of system administration scripts and utilities designed to keep an Arch Linux workstation clean, updated, and resilient.
safe-update is a Bash-based update orchestrator for Arch Linux and CachyOS systems using Btrfs and Snapper. It keeps the original rollback-first workflow while adding a modular architecture, runtime configuration, structured reporting, and multidimensional operational risk analysis.
- Modular update workflow
scripts/safe-updateis the orchestration entrypoint and sources focused modules fromlib/for config, logging, notifications, snapshots, risk analysis, utilities, and report generation. - Context-aware risk analysis
Pending updates are classified intoCRITICAL,HIGH,MEDIUM, andLOWbuckets while also tracking reboot, boot-chain, graphics-stack, core-system, and AUR-related impact metadata. - Rollback-first safety
A pre-update Btrfs snapshot is created withsnapperbefore upgrades run. - Human confirmation gates
Critical updates still require explicit confirmation before the script proceeds. - Structured observability
Each run produces both a human-readable log and a JSON report for future automation, dashboards, or advisory correlation. - Advisory groundwork
Runtime flags and report fields are in place for future Arch Linux and CachyOS news/advisory integration without introducing opaque autonomous decisions.
To use safe-update, your system must have:
- Arch Linux or a compatible derivative such as CachyOS
- pacman-contrib installed for
checkupdates, which safely refreshes a temporary pacman database before detection - Paru installed as the AUR helper for
paru -Syu - Btrfs with Snapper configured
- libnotify (providing
notify-send) for desktop alerts - jq for structured report generation and validation; when
ENABLE_REPORTS=true(the default),safe-updatefails fast ifjqis unavailable
workstation-ops/
├── config/
│ └── safe-update.conf
├── lib/
│ ├── config.sh
│ ├── logging.sh
│ ├── notifications.sh
│ ├── reports.sh
│ ├── risk.sh
│ ├── snapshots.sh
│ └── utils.sh
├── scripts/
│ └── safe-update
├── VERSION
└── tests/
git clone https://github.com/RogFed/workstation-ops.git
cd workstation-opschmod +x scripts/safe-update tests/run./scripts/safe-updateDefaults live in:
config/safe-update.conf
The config file is sourced by Bash, so it should contain only trusted shell assignments from a trusted local source.
Current runtime settings include:
SAFE_UPDATE_DATA_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/safe-update"
ENABLE_NOTIFICATIONS=true
ENABLE_ARCH_NEWS=true
ENABLE_CACHYOS_NEWS=true
ENABLE_REPORTS=true
TIMELINE_RETENTION=6
UPDATE_SNAPSHOT_RETENTION=5./tests/run./tests/run tests/unit/risk_spec.shbash -n scripts/safe-updateshellcheck scripts/safe-updateRuntime-generated data lives outside the repository under:
~/.local/share/safe-update/
├── logs/
├── reports/
├── cache/
└── state/
Key outputs:
- Logs:
~/.local/share/safe-update/logs/update-YYYY-MM-DDTHHMMSS.log - Reports:
~/.local/share/safe-update/reports/report-YYYY-MM-DDTHHMMSS.json(with an automatic suffix only if a same-second collision occurs) - Snapshots:
pre-update-YYYY-MM-DDTHHMMSS
Reports are immutable JSON records written with jq and validated before they are persisted.
Current report fields include:
versiontimestamphostnamekernel_versionbootloadersnapshot.created,snapshot.name,snapshot.id(optional;nullwhen Snapper does not expose a parsable snapshot ID)updates.critical,updates.high,updates.medium,updates.lowpackage_risk_metadata[]objects withname,severity,reboot_required,boot_impact,graphics_impact,core_system_impact,userland_only, andaur_packagerisk_summary.critical_package_count,risk_summary.high_package_count,risk_summary.medium_package_count,risk_summary.low_package_countrisk_summary.graphics_stack_changed,risk_summary.boot_chain_changed,risk_summary.core_system_changedrisk_summary.reboot_required,risk_summary.aur_package_countreboot_requiredupdate_resultduration_secondsadvisory_flags.arch_news_detected,advisory_flags.cachyos_news_detectedlog_file,report_path