diff --git a/.github/workflows/acceptance.yml b/.github/workflows/acceptance.yml new file mode 100644 index 0000000..5aa95d3 --- /dev/null +++ b/.github/workflows/acceptance.yml @@ -0,0 +1,76 @@ +# L4b/L5 - runtime acceptance of the built ISO on an x86_64 runner. +# +# Two jobs, deliberately separate so a live-desktop regression is +# distinguishable from a security-cleanup regression: +# +# live-health boots the ISO, logs in on serial and asserts on RUNNING +# state: graphical.target, SDDM, Hyprland, session +# components, NetworkManager, DNS, PipeWire, portals. +# deloop-contract extracts the SquashFS, runs simulationos-deloop exactly as +# Calamares does, and asserts the installed-system security +# gates (liveuser gone, autologin gone, NOPASSWD gone, root +# locked, archiso initramfs hook gone). +name: acceptance + +on: + workflow_dispatch: + workflow_call: + inputs: + artifact: + description: Name of the ISO artifact to test + type: string + required: true + +permissions: + contents: read + +jobs: + live-health: + name: Live system health + runs-on: ubuntu-latest + timeout-minutes: 60 + steps: + - uses: actions/checkout@v4 + - name: Install QEMU and OVMF + run: | + sudo apt-get update -qq + sudo apt-get install -y -qq qemu-system-x86 ovmf + - name: Download the ISO + uses: actions/download-artifact@v4 + with: + name: ${{ inputs.artifact }} + path: out + - name: KVM availability + run: | + # Hosted runners have no nested virtualisation; TCG is correct but + # slow. This is recorded so a timeout can be attributed correctly. + if [ -e /dev/kvm ]; then echo "KVM available"; else echo "no /dev/kvm -> TCG"; fi + - name: Live health checks + env: + SIMOS_LIVE_TIMEOUT: '2100' + run: ./scripts/live-health.sh + - name: Upload live log + if: always() + uses: actions/upload-artifact@v4 + with: + name: live-health-log-${{ github.sha }} + path: out/live-health.log + if-no-files-found: ignore + + deloop-contract: + name: De-live security contract + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v4 + - name: Install extraction tools + run: | + sudo apt-get update -qq + sudo apt-get install -y -qq squashfs-tools libarchive-tools + - name: Download the ISO + uses: actions/download-artifact@v4 + with: + name: ${{ inputs.artifact }} + path: out + - name: Verify the de-live transformation + run: sudo ./scripts/deloop-test.sh diff --git a/.github/workflows/boot.yml b/.github/workflows/boot.yml new file mode 100644 index 0000000..7b5dcf0 --- /dev/null +++ b/.github/workflows/boot.yml @@ -0,0 +1,63 @@ +# L4 - boot the built ISO in QEMU and require proof it reached a target. +# +# Split from iso.yml so a boot regression is distinguishable from a build +# regression at a glance. +name: boot-test + +on: + workflow_dispatch: + workflow_call: + inputs: + artifact: + description: Name of the ISO artifact to boot + type: string + required: true + +permissions: + contents: read + +jobs: + boot: + name: QEMU boot (${{ matrix.firmware }}) + runs-on: ubuntu-latest + timeout-minutes: 45 + strategy: + fail-fast: false + matrix: + # SimulationOS declares bios.syslinux and uefi.systemd-boot, so both + # are tested. Do not add firmware here that the profile does not + # actually support. + firmware: [uefi, bios] + steps: + - uses: actions/checkout@v4 + + - name: Install QEMU and OVMF + run: | + sudo apt-get update -qq + sudo apt-get install -y -qq qemu-system-x86 ovmf + + - name: Download the ISO built by this pipeline + uses: actions/download-artifact@v4 + with: + name: ${{ inputs.artifact }} + path: out + + - name: Enable KVM if the runner provides it + run: | + # Hosted runners usually have no nested virtualisation; TCG is the + # fallback and is slow but correct. + [ -e /dev/kvm ] && echo "KVM available" || echo "no /dev/kvm; using TCG" + + - name: Boot test + env: + SIMOS_BOOT_TEST_FIRMWARE: ${{ matrix.firmware }} + SIMOS_BOOT_TEST_TIMEOUT: '1500' + run: ./scripts/boot-test.sh + + - name: Upload serial console log + if: always() + uses: actions/upload-artifact@v4 + with: + name: boot-log-${{ matrix.firmware }} + path: out/boot-test-*.log + if-no-files-found: ignore diff --git a/.github/workflows/iso.yml b/.github/workflows/iso.yml new file mode 100644 index 0000000..24218f7 --- /dev/null +++ b/.github/workflows/iso.yml @@ -0,0 +1,100 @@ +# L2/L3 - build the ISO in a clean environment and inspect the artefact. +# +# Runs ./build.sh, the same entry point developers use. build.sh detects that +# the runner is not Arch and drives an x86_64 Arch container itself, so there +# is exactly one build engine and CI cannot drift from local behaviour. +name: iso + +on: + push: + branches: [main, 'feat/**'] + paths-ignore: ['**.md', 'docs/**', 'LICENSE'] + pull_request: + paths-ignore: ['**.md', 'docs/**', 'LICENSE'] + workflow_dispatch: + workflow_call: + +permissions: + contents: read + +jobs: + validate: + uses: ./.github/workflows/validate.yml + + build: + name: Build ISO + needs: validate + runs-on: ubuntu-latest + timeout-minutes: 90 + outputs: + iso_name: ${{ steps.meta.outputs.iso_name }} + iso_sha256: ${{ steps.meta.outputs.iso_sha256 }} + steps: + - uses: actions/checkout@v4 + + - name: Free disk space + # A 2.1 GB ISO plus a ~4 GB unpacked rootfs plus ~1.4 GB of packages + # does not fit alongside the runner's preinstalled toolchains. + run: | + df -h / + sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc \ + /usr/local/share/boost "$AGENT_TOOLSDIRECTORY" || true + sudo apt-get clean || true + df -h / + + - name: Install inspection tools + # inspect-iso.sh reads the ISO9660 filesystem with bsdtar, which + # ubuntu-latest does not ship (it lives in libarchive-tools). + run: sudo apt-get update -qq && sudo apt-get install -y -qq libarchive-tools + + - name: Build (via ./build.sh) + run: ./build.sh + + - name: Inspect the artefact + run: ./scripts/inspect-iso.sh + + - name: Collect metadata + id: meta + run: | + iso="$(ls -1 out/simulationos-*.iso | head -1)" + echo "iso_name=$(basename "$iso")" >> "$GITHUB_OUTPUT" + echo "iso_sha256=$(cut -d' ' -f1 < "$iso.sha256")" >> "$GITHUB_OUTPUT" + echo "### SimulationOS ISO" >> "$GITHUB_STEP_SUMMARY" + echo '```json' >> "$GITHUB_STEP_SUMMARY" + cat out/build-info.json >> "$GITHUB_STEP_SUMMARY" + echo '```' >> "$GITHUB_STEP_SUMMARY" + + - name: Upload ISO + uses: actions/upload-artifact@v4 + with: + name: simulationos-alpha-${{ github.sha }}-x86_64 + path: | + out/*.iso + out/*.iso.sha256 + out/build-info.json + retention-days: 14 + if-no-files-found: error + compression-level: 0 + + - name: Upload build log + if: always() + uses: actions/upload-artifact@v4 + with: + name: build-log-${{ github.sha }} + path: out/build.log + retention-days: 14 + if-no-files-found: ignore + + boot: + name: Boot test + needs: build + uses: ./.github/workflows/boot.yml + with: + artifact: simulationos-alpha-${{ github.sha }}-x86_64 + + acceptance: + name: Runtime acceptance + needs: [build, boot] + uses: ./.github/workflows/acceptance.yml + with: + artifact: simulationos-alpha-${{ github.sha }}-x86_64 diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml new file mode 100644 index 0000000..786d35b --- /dev/null +++ b/.github/workflows/validate.yml @@ -0,0 +1,85 @@ +# L1 - fast static validation. Runs on every push and PR. +# Deliberately needs no container and no pacman, so it finishes in seconds. +name: validate + +on: + push: + branches: ['**'] + pull_request: + workflow_call: + +permissions: + contents: read + +jobs: + static: + name: Static validation + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install shellcheck + run: sudo apt-get update -qq && sudo apt-get install -y -qq shellcheck + + - name: Validate profile + run: ./scripts/validate-profile.sh + + - name: Shell syntax + run: | + fail=0 + while IFS= read -r f; do + head -1 "$f" | grep -qE '^#!.*(bash|sh)' || continue + bash -n "$f" || { echo "syntax error: $f"; fail=1; } + done < <(git ls-files | grep -vE '\.(md|png|svg|conf|desc|qml|css|jsonc)$') + exit $fail + + - name: ShellCheck + run: | + shellcheck -S warning build.sh scripts/*.sh \ + airootfs/usr/local/bin/simos-* \ + airootfs/usr/local/bin/simulationos-install \ + airootfs/usr/share/simulationos/calamares/scripts/simulationos-deloop + + - name: Installer config is valid YAML + run: | + python3 - <<'PY' + import glob, sys, yaml + bad = 0 + files = glob.glob("airootfs/usr/share/simulationos/calamares/**/*.conf", recursive=True) + files += glob.glob("airootfs/usr/share/simulationos/calamares/branding/*/branding.desc") + for f in files: + try: + yaml.safe_load(open(f)) + except Exception as e: + print(f"YAML ERROR {f}: {e}"); bad = 1 + print(f"checked {len(files)} installer config files") + sys.exit(bad) + PY + + - name: Waybar config is valid JSON + run: | + python3 - <<'PY' + import json, re, sys + t = open("airootfs/etc/skel/.config/waybar/config.jsonc").read() + json.loads(re.sub(r'^\s*//.*$', '', t, flags=re.M)) + print("waybar config.jsonc OK") + PY + + - name: No secrets committed + run: | + # Deliberately narrow: private keys and obvious credential material. + if git grep -nIE 'BEGIN (RSA|OPENSSH|PGP|EC) PRIVATE KEY|ghp_[A-Za-z0-9]{30,}|AKIA[0-9A-Z]{16}' -- . ; then + echo "::error::possible secret committed"; exit 1 + fi + echo "no secrets found" + + - name: Validator must actually catch regressions + run: | + # A validator that never fails is worthless. Prove it still bites. + set -e + tmp=$(mktemp -d); cp -R . "$tmp/repo"; cd "$tmp/repo" + sed -i 's/vmlinuz-linux-cachyos/vmlinuz-linux/' efiboot/loader/entries/01-simulationos-linux.conf + if ./scripts/validate-profile.sh >/dev/null 2>&1; then + echo "::error::validator did NOT catch an injected kernel-name regression"; exit 1 + fi + echo "validator correctly rejected the injected regression" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1cf22f9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +# mkarchiso build artefacts +/work/ +/out/ +# local pacman package cache used by the containerised builder +/.cache/ +/artifacts/ +.DS_Store diff --git a/README.md b/README.md index f62da2b..97f781b 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,331 @@ # SimulationOS -SimulationOS Arch-Based distribution offering an ideal working environment especially for programming, Networking and Gaming! + +An Arch-based Linux distribution built around Hyprland, shipped as a live ISO +with a graphical installer. + +SimulationOS is an **archiso profile**: this repository is not an operating +system you run, it is the build recipe that `mkarchiso` turns into + +``` +out/simulationos--x86_64.iso +``` + +> **Status: Alpha.** The profile builds a complete live desktop and installs +> itself. See [Alpha limitations](#alpha-limitations) for what is not done yet, +> and [Verification status](#verification-status) for what has actually been +> tested versus only statically checked. + +--- + +## Architecture + +``` +Arch Linux base distribution, [core] [extra] [multilib] + | +ArchISO profile format, initramfs hooks, ISO assembly + | +CachyOS repositories only for what is exclusive to them + | +linux-cachyos the kernel SimulationOS ships + | +SimulationOS live layer airootfs/ overlay: identity, live user, services + | +Hyprland Wayland session, started by SDDM + | +Calamares graphical installer, SimulationOS configuration +``` + +Three sources are deliberately kept distinct: + +| Layer | Role | +|---|---| +| **ArchISO** | The architectural baseline. Boot modes, `profiledef.sh` semantics, initramfs hooks and the `/etc/skel` mechanism follow upstream exactly. | +| **CachyOS** | A *component supplier*, not a template. Used for `linux-cachyos`, `cachyos-calamares`, `ckbcomp`, `mkinitcpio-openswap` and the keyring/mirrorlist — nothing else. | +| **SimulationOS** | Identity, live session design, desktop configuration and installer configuration. | + +Arch repositories are listed **before** `[cachyos]` in `pacman.conf`, so a +package that exists in both comes from Arch. SimulationOS does not adopt the +CachyOS optimised package set. + +Full design rationale: [`docs/architecture.md`](docs/architecture.md). + +--- + +## Prerequisites + +Building an ISO requires an **Arch Linux x86_64** host running as root: + +| Requirement | Why | +|---|---| +| Linux, `x86_64` | `mkarchiso` is Linux-only; a non-x86_64 host would pacstrap the wrong architecture. | +| `archiso` | Provides `mkarchiso`. | +| `cachyos-keyring`, key `F3B607488DB35A47` trusted | `pacstrap` verifies CachyOS package signatures against the **build host** keyring. Signature checking is never disabled. | +| ~20 GB free disk | Work directory plus the ISO. | +| Network access | Package downloads. | + +Provision the CachyOS key on the build host (the official CachyOS procedure): + +```bash +sudo pacman-key --recv-keys F3B607488DB35A47 --keyserver keyserver.ubuntu.com +sudo pacman-key --lsign-key F3B607488DB35A47 +sudo pacman -Sy --config ./pacman.conf cachyos-keyring cachyos-mirrorlist +sudo pacman -S archiso +``` + +`scripts/build-iso.sh` checks every one of these and refuses to start with an +exact remediation message rather than failing halfway through a build. + +### Not building on Arch? + +You do not need to do anything special. `./build.sh` detects the host and runs +the build inside an x86_64 Arch container automatically: + +```bash +./build.sh +``` + +It prints exactly what it decided before doing any work: + +``` +==> Host: Darwin arm64 +==> Target: linux x86_64 +==> Builder: container +``` + +The container is pinned to `--platform linux/amd64`, so an arm64 host can +never silently produce an arm64 ISO. On such a host the builder runs under +emulation: correct, but **much** slower than a native x86_64 machine. Prefer +real x86_64 hardware or a VM for routine builds. + +--- + +## Repository structure + +``` +SimulationOS/ +├── build.sh THE build entry point +├── profiledef.sh archiso manifest (ISO name, boot modes, permissions) +├── packages.x86_64 everything installed into the ISO +├── pacman.conf BUILD HOST repo config (explicit CachyOS Server=) +├── bootstrap_packages.x86_64 minimal set for the bootstrap build mode +│ +├── airootfs/ overlay copied into the ISO root +│ ├── etc/ +│ │ ├── os-release, issue, motd, hostname, hosts identity +│ │ ├── passwd, shadow, group, gshadow the liveuser account +│ │ ├── pacman.conf live/installed repo config +│ │ ├── sddm.conf.d/ greeter + live autologin +│ │ ├── sudoers.d/, polkit-1/rules.d/ live-only privilege policy +│ │ ├── skel/.config/{hypr,waybar,kitty,mako}/ the desktop, via /etc/skel +│ │ └── systemd/{system,user}/ explicit service enablement +│ └── usr/ +│ ├── local/bin/ simulationos-install, simos-* helpers +│ └── share/ +│ ├── applications/ "Install SimulationOS" launcher +│ ├── backgrounds/simulationos/ +│ ├── pixmaps/ +│ └── simulationos/calamares/ the whole installer configuration +│ +├── efiboot/ systemd-boot entries (UEFI) +├── syslinux/ syslinux menu (BIOS) + PXE +├── grub/loopback.cfg boot this ISO from an existing GRUB +│ +├── scripts/ +│ ├── validate-profile.sh static consistency checks +│ ├── build-iso.sh environment checks + mkarchiso + checksum +│ ├── clean-build.sh remove work/ and out/ +│ ├── inspect-iso.sh L3 artefact inspection +│ ├── test-iso.sh boot it in QEMU (UEFI or BIOS) +│ └── make-wallpaper.py regenerate the wallpaper asset +│ +├── .github/workflows/ +│ ├── validate.yml L1 static validation (seconds, no container) +│ └── iso.yml L2/L3 clean build + artefact inspection +│ +└── docs/ + ├── architecture.md design rationale + ├── adr/ 15 decision records + └── research/sources.md primary-source findings +``` + +--- + +## Workflow + +### Validate + +Runs anywhere, including macOS — it never needs `pacman`: + +```bash +./scripts/validate-profile.sh +``` + +It fails the build on things that would otherwise only surface at boot: +boot entries naming a kernel the profile does not install, Hyprland launching +binaries nobody ships, developer-specific paths, dangling systemd symlinks, +missing Calamares module configs, a `deloop` script that stopped removing the +archiso initramfs hook, shell syntax errors, and more. + +### Build + +```bash +./build.sh +``` + +This is the **only** build entry point — developers, CI and releases all use +it, so a local build and a CI build cannot drift. It runs natively on Arch +x86_64 and in a container everywhere else. + +```bash +./build.sh --validate # static checks only +./build.sh --clean # wipe work/ and out/ first +./build.sh --no-cache # ignore the local package cache +./build.sh --help +``` + +Produces, in `out/`: + +``` +simulationos--x86_64.iso +simulationos--x86_64.iso.sha256 +build-info.json commit, archiso version, checksum, duration +build.log +``` + +### Clean + +```bash +./scripts/clean-build.sh # remove work/ and out/ +./scripts/clean-build.sh --keep-iso # remove work/ only +``` + +### Test in a VM + +```bash +./scripts/test-iso.sh # UEFI (OVMF) +./scripts/test-iso.sh --bios # legacy BIOS / syslinux +./scripts/test-iso.sh --install # attach a blank 30G disk and install +./scripts/test-iso.sh --boot-disk # boot ONLY that disk, no ISO +``` + +The last two are the real acceptance test: install to the disk, then boot the +disk with no medium attached. + +--- + +## Boot and installation flow + +**Live medium** + +``` +Firmware → syslinux (BIOS) / systemd-boot (UEFI) + → linux-cachyos + archiso initramfs + → SquashFS root (/run/archiso) + → systemd → graphical.target + → SDDM → autologin liveuser → Hyprland +``` + +**Installation** + +``` +Live session → "Install SimulationOS" → Calamares + → partition → mount → unpackfs (copy the live SquashFS) + → users → networkcfg → services-systemd → packages (drop the installer) + → removeuser (liveuser) → simulationos-deloop (strip live config) + → initcpiocfg → initcpio (rebuild a NON-archiso initramfs) + → grubcfg → bootloader (GRUB) → umount + → reboot into the installed system +``` + +Because the offline installer copies the live filesystem verbatim, the target +initially inherits every live concession. `simulationos-deloop` removes them: +SDDM autologin, tty autologin, NOPASSWD sudo (replaced by a password-prompting +`%wheel` rule), the permissive polkit rule, the archiso initramfs hook, +archiso-only units, `/home/liveuser` — and it **locks the root account**, which +the live medium leaves passwordless. + +--- + +## Alpha limitations + +- **NVIDIA:** no proprietary driver and no `chwd` integration. The previous + half-wired `chwd`-dependent NVIDIA scripts were removed rather than shipped + broken. NVIDIA hardware falls back to `nouveau`. +- **Installer model:** offline only. The `unpackfs` module copies the live + SquashFS; there is no online package selection. +- **Bootloaders:** the installed system always gets GRUB. No systemd-boot, + rEFInd or Limine choice. +- **No disk encryption flow** has been exercised, though the LUKS-capable + Calamares modules and `cryptsetup` are present. +- **Secure Boot** is not supported. +- **Locale defaults** to `C.UTF-8` on the live medium; the installer sets the + real locale for the target. +- **sshd is installed but not enabled** on the live medium, unlike upstream + archiso. Start it manually after setting a password if you need it. +- The SquashFS is `xz`-compressed, which favours ISO size over boot speed. + +--- + +## Verification status + +Everything below was done on a **macOS arm64** workstation, which cannot run +`mkarchiso`, `pacman` or an x86_64 QEMU guest. Nothing here claims a boot that +did not happen. + +| Item | Status | Evidence | +|---|---|---| +| Upstream archiso/CachyOS/Calamares research | VERIFIED | primary sources, file+line, in `docs/research/sources.md` | +| Dependency resolution against real repos | VERIFIED | x86_64 Arch container: 144 requested -> **577 resolved**, exactly 6 from `[cachyos]` | +| Profile internal consistency | VERIFIED | `validate-profile.sh` passes | +| Validator actually catches regressions | VERIFIED | 11/11 fault injections caught | +| Shell syntax + shellcheck + YAML/JSON | VERIFIED | clean | +| **ISO builds end to end** | **VERIFIED** | `simulationos-2026.09.27-x86_64.iso`, 2,186,756,096 bytes, sha256 `caf09548…6f77e8`, archiso 90-1, mkarchiso 803 s | +| **`linux-cachyos` is the kernel in the artefact** | **VERIFIED** | ISO contains `arch/boot/x86_64/vmlinuz-linux-cachyos` + `initramfs-linux-cachyos.img` | +| **Both bootloaders present in the artefact** | **VERIFIED** | `boot/syslinux/isolinux.bin` (BIOS) and `EFI/BOOT/BOOTX64.EFI` + `loader/entries/01-simulationos-linux.conf` (UEFI) | +| **Boot menus branded, kernel references correct** | **VERIFIED** | menus extracted *from the ISO*: say SimulationOS, no "Arch Linux install medium", both point at `vmlinuz-linux-cachyos` | +| **Installer source path matches the ISO layout** | **VERIFIED** | `arch/x86_64/airootfs.sfs` present and equals the `unpackfs.conf` source | +| **ISO boots (UEFI)** | **VERIFIED** | QEMU+OVMF: systemd-boot menu -> kernel -> `SimulationOS Alpha Linux 7.2.7-1-cachyos (ttyS0)` / `simulationos login:` | +| ISO boots (BIOS/syslinux) | NOT TESTED | `./scripts/boot-test.sh` with `SIMOS_BOOT_TEST_FIRMWARE=bios` | +| Hyprland live session | NOT TESTED | requires a boot | +| Calamares run / full install / installed-system boot | NOT TESTED | requires a boot | +| Hardware (real GPUs, Wi-Fi, laptops) | NOT TESTED | no hardware matrix yet | + +The ISO was built on macOS arm64 through the containerised x86_64 builder and +booted under QEMU/TCG emulation. The UEFI boot reached a login prompt showing +the SimulationOS banner on the CachyOS kernel, which proves firmware -> +systemd-boot -> kernel -> initramfs -> systemd -> getty end to end. + +It does **not** prove the graphical session: SDDM and Hyprland starting, the +installer running, or an installed system booting on its own are all still +untested. Kernel and systemd status output goes to tty0 rather than the serial +console, so those stages are reported as "n/a" rather than as failures. + +The first real run should be: + +```bash +./scripts/validate-profile.sh && sudo ./scripts/build-iso.sh +./scripts/test-iso.sh --install +./scripts/test-iso.sh --boot-disk +``` + +--- + +## Upstream dependencies + +| Project | Used for | Licence | +|---|---|---| +| [Arch Linux](https://archlinux.org) | Base system and repositories | various | +| [archiso](https://gitlab.archlinux.org/archlinux/archiso) | ISO build system, profile format | GPL-3.0 | +| [CachyOS](https://cachyos.org) | `linux-cachyos`, `cachyos-calamares`, keyring/mirrorlist | GPL-3.0 and others | +| [Hyprland](https://hypr.land) | Wayland compositor | BSD-3-Clause | +| [Calamares](https://calamares.io) | Installer framework | GPL-3.0 | + +SimulationOS packages and configures these projects; it does not claim +authorship of them. `syslinux/splash.png` and the `livecd-sound` accessibility +helper are inherited from archiso and remain under their original terms. + +--- + +## Licence + +See [LICENSE](LICENSE). diff --git a/airootfs/etc/hostname b/airootfs/etc/hostname index ea2d6f7..056011c 100644 --- a/airootfs/etc/hostname +++ b/airootfs/etc/hostname @@ -1 +1 @@ -SimulationOS +simulationos diff --git a/airootfs/etc/hosts b/airootfs/etc/hosts index ed7bc42..26bf5c3 100644 --- a/airootfs/etc/hosts +++ b/airootfs/etc/hosts @@ -1 +1,6 @@ -185.199.108.133 raw.githubusercontent.com +# Static table lookup for hostnames. +# See hosts(5) for details. + +127.0.0.1 localhost +::1 localhost +127.0.1.1 simulationos.localdomain simulationos diff --git a/airootfs/etc/issue b/airootfs/etc/issue new file mode 100644 index 0000000..1ee6d04 --- /dev/null +++ b/airootfs/etc/issue @@ -0,0 +1,3 @@ + +\e[38;2;23;147;209mSimulationOS Alpha\e[0m \s \r (\l) + diff --git a/airootfs/etc/mkinitcpio.conf.d/archiso.conf b/airootfs/etc/mkinitcpio.conf.d/archiso.conf index 1794a5e..a11b801 100644 --- a/airootfs/etc/mkinitcpio.conf.d/archiso.conf +++ b/airootfs/etc/mkinitcpio.conf.d/archiso.conf @@ -1,5 +1,14 @@ -HOOKS=(base udev microcode modconf kms memdisk archiso archiso_loop_mnt archiso_pxe_common archiso_pxe_nbd archiso_pxe_http archiso_pxe_nfs block filesystems keyboard) +# SimulationOS live medium initramfs. +# +# Upstream archiso also carries archiso_pxe_common / _nbd / _http / _nfs for +# netboot. SimulationOS does not support PXE: the product journey is +# download -> flash USB -> boot. Those hooks are omitted rather than left in +# place, because each one needs support files we would otherwise have to ship: +# archiso_pxe_common -> /usr/lib/initcpio/ipconfig (mkinitcpio-nfs-utils) +# archiso_pxe_nbd -> nbd-client (nbd) +# archiso_pxe_nfs -> /usr/lib/initcpio/nfsmount (mkinitcpio-nfs-utils) +# Keeping the hooks without those packages makes mkinitcpio fail. +# validate-profile.sh enforces the hook -> package relationship. +HOOKS=(base udev microcode modconf kms memdisk archiso archiso_loop_mnt block filesystems keyboard) COMPRESSION="xz" - - - +COMPRESSION_OPTIONS=(-9e) diff --git a/airootfs/etc/mkinitcpio.d/linux.preset b/airootfs/etc/mkinitcpio.d/linux.preset deleted file mode 100644 index b83a16d..0000000 --- a/airootfs/etc/mkinitcpio.d/linux.preset +++ /dev/null @@ -1,8 +0,0 @@ -# mkinitcpio preset file for the 'linux' package on archiso - -PRESETS=('archiso') - -ALL_kver='/boot/vmlinuz-linux-simos' -archiso_config='/etc/mkinitcpio.conf.d/archiso.conf' - -archiso_image="/boot/initramfs-linux-simos.img" diff --git a/airootfs/etc/modprobe.d/broadcom-wl.conf b/airootfs/etc/modprobe.d/broadcom-wl.conf deleted file mode 100644 index 0eae70c..0000000 --- a/airootfs/etc/modprobe.d/broadcom-wl.conf +++ /dev/null @@ -1,7 +0,0 @@ -# The broadcom-wl package requires some modules to be disabled in order to use -# wl. Since the ISO image needs to cover many hardware cases, this file -# overrides the default blacklist in /usr/lib/modprobe.d/ -# -# If you need to use wl, you may need to delete this file, then `rmmod` any -# already-loaded modules that are now blacklisted before proceeding to modprobe -# wl itself. diff --git a/airootfs/etc/modprobe.d/nvidia-loader.conf b/airootfs/etc/modprobe.d/nvidia-loader.conf deleted file mode 100644 index 9b7e518..0000000 --- a/airootfs/etc/modprobe.d/nvidia-loader.conf +++ /dev/null @@ -1,6 +0,0 @@ -# Forwards all NVIDIA module load requests to a "smart" loader that selects -# correct version of the module depending on used hardware. -install nvidia /usr/local/bin/nvidia-module-loader -install nvidia_drm /usr/local/bin/nvidia-module-loader -install nvidia_uvm /usr/local/bin/nvidia-module-loader -install nvidia_modeset /usr/local/bin/nvidia-module-loader diff --git a/airootfs/etc/motd b/airootfs/etc/motd index 4d9eda1..6da0b68 100644 --- a/airootfs/etc/motd +++ b/airootfs/etc/motd @@ -1,11 +1,18 @@ -To install Arch Linux follow the installation guide: -https://wiki.archlinux.org/title/Installation_guide -For Wi-Fi, authenticate to the wireless network using the iwctl utility. -For mobile broadband (WWAN) modems, connect with the mmcli utility. -Ethernet, WLAN and WWAN interfaces using DHCP should work automatically. + SimulationOS Alpha - live environment -After connecting to the internet, the installation guide can be accessed -via the convenience script Installation_guide. + The graphical desktop starts automatically. If you are reading this on a + text console, the display manager may have failed; check: + + systemctl status display-manager + journalctl -b -u sddm + + To install SimulationOS to a disk, use "Install SimulationOS" in the + application launcher, or run: + + simulationos-install + + Network: nmtui / nmcli device wifi list + Audio: wpctl status + Logs: journalctl -b -                                           diff --git a/airootfs/etc/os-release b/airootfs/etc/os-release index b3f7ad0..20b6d7f 100644 --- a/airootfs/etc/os-release +++ b/airootfs/etc/os-release @@ -1,10 +1,11 @@ NAME="SimulationOS" -PRETTY_NAME="SimulationOS" -ID=arch +PRETTY_NAME="SimulationOS Alpha" +ID=simulationos +ID_LIKE=arch BUILD_ID=rolling ANSI_COLOR="38;2;23;147;209" HOME_URL="https://github.com/HaiderBassem/SimulationOS" DOCUMENTATION_URL="https://github.com/HaiderBassem/SimulationOS/blob/main/README.md" -SUPPORT_URL="https://github.com/HaiderBassem/SimulationOS" +SUPPORT_URL="https://github.com/HaiderBassem/SimulationOS/issues" BUG_REPORT_URL="https://github.com/HaiderBassem/SimulationOS/issues" -LOGO=SimulationOS \ No newline at end of file +LOGO=simulationos diff --git a/airootfs/etc/pacman-more.conf b/airootfs/etc/pacman-more.conf deleted file mode 100644 index 6292620..0000000 --- a/airootfs/etc/pacman-more.conf +++ /dev/null @@ -1,134 +0,0 @@ -# CachyOS's configration -# /etc/pacman.conf -# -# See the pacman.conf(5) manpage for option and repository directives - -# -# GENERAL OPTIONS -# -[options] -# The following paths are commented out with their default values listed. -# If you wish to use different paths, uncomment and update the paths. -#RootDir = / -#DBPath = /var/lib/pacman/ -#CacheDir = /var/cache/pacman/pkg/ -#LogFile = /var/log/pacman.log -#GPGDir = /etc/pacman.d/gnupg/ -#HookDir = /etc/pacman.d/hooks/ -HoldPkg = pacman glibc -#XferCommand = /usr/bin/curl -L -C - -f -o %o %u -#XferCommand = /usr/bin/wget --passive-ftp -c -O %o %u -#CleanMethod = KeepInstalled -#UseDelta = 0.7 -Architecture = auto - -# Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup -#IgnorePkg = -#IgnoreGroup = - -#NoUpgrade = -#NoExtract = - -# Misc options -#UseSyslog -Color -ILoveCandy -#NoProgressBar -#CheckSpace -VerbosePkgLists -DisableDownloadTimeout -ParallelDownloads = 10 -DownloadUser = alpm -#DisableSandbox - -# By default, pacman accepts packages signed by keys that its local keyring -# trusts (see pacman-key and its man page), as well as unsigned packages. -SigLevel = Required DatabaseOptional -LocalFileSigLevel = Optional -#RemoteFileSigLevel = Required - -# NOTE: You must run `pacman-key --init` before first using pacman; the local -# keyring can then be populated with the keys of all official Arch Linux -# packagers with `pacman-key --populate archlinux`. - -# -# REPOSITORIES -# - can be defined here or included from another file -# - pacman will search repositories in the order defined here -# - local/custom mirrors can be added here or in separate files -# - repositories listed first will take precedence when packages -# have identical names, regardless of version number -# - URLs will have $repo replaced by the name of the current repo -# - URLs will have $arch replaced by the name of the architecture -# -# Repository entries are of the format: -# [repo-name] -# Server = ServerName -# Include = IncludePath -# -# The header [repo-name] is crucial - it must be present and -# uncommented to enable the repo. -# - -# cachyos repos - -#[cachyos-znver4] -#Include = /etc/pacman.d/cachyos-v4-mirrorlist - -#[cachyos-core-znver4] -#Include = /etc/pacman.d/cachyos-v4-mirrorlist - -#[cachyos-extra-znver4] -#Include = /etc/pacman.d/cachyos-v4-mirrorlist - -#[cachyos-v4] -#Include = /etc/pacman.d/cachyos-v4-mirrorlist - -#[cachyos-core-v4] -#Include = /etc/pacman.d/cachyos-v4-mirrorlist - -#[cachyos-extra-v4] -#Include = /etc/pacman.d/cachyos-v4-mirrorlist - -#[cachyos-v3] -#Include = /etc/pacman.d/cachyos-v3-mirrorlist - -#[cachyos-core-v3] -#Include = /etc/pacman.d/cachyos-v3-mirrorlist - -#[cachyos-extra-v3] -#Include = /etc/pacman.d/cachyos-v3-mirrorlist - -[cachyos] -Include = /etc/pacman.d/cachyos-mirrorlist - -# The testing repositories are disabled by default. To enable, uncomment the -# repo name header and Include lines. You can add preferred servers immediately -# after the header, and they will be used before the default mirrors. - -#[core-testing] -#Include = /etc/pacman.d/mirrorlist - -[core] -Include = /etc/pacman.d/mirrorlist - -#[extra-testing] -#Include = /etc/pacman.d/mirrorlist - -[extra] -Include = /etc/pacman.d/mirrorlist - -# If you want to run 32 bit applications on your x86_64 system, -# enable the multilib repositories as required here. - -#[multilib-testing] -#Include = /etc/pacman.d/mirrorlist - -[multilib] -Include = /etc/pacman.d/mirrorlist - -# An example of a custom package repository. See the pacman manpage for -# tips on creating your own repositories. -#[custom] -#SigLevel = Optional TrustAll -#Server = file:///home/custompkgs diff --git a/airootfs/etc/pacman.conf b/airootfs/etc/pacman.conf index 57daefc..5584ccc 100644 --- a/airootfs/etc/pacman.conf +++ b/airootfs/etc/pacman.conf @@ -1,106 +1,38 @@ # -# /etc/pacman.conf +# /etc/pacman.conf - SimulationOS # -# See the pacman.conf(5) manpage for option and repository directives - -# -# GENERAL OPTIONS +# See the pacman.conf(5) manpage for option and repository directives. # + [options] -# The following paths are commented out with their default values listed. -# If you wish to use different paths, uncomment and update the paths. -#RootDir = / -#DBPath = /var/lib/pacman/ -#CacheDir = /var/cache/pacman/pkg/ -#LogFile = /var/log/pacman.log -#GPGDir = /etc/pacman.d/gnupg/ -#HookDir = /etc/pacman.d/hooks/ HoldPkg = pacman glibc -#XferCommand = /usr/bin/curl -L -C - -f -o %o %u -#XferCommand = /usr/bin/wget --passive-ftp -c -O %o %u -#CleanMethod = KeepInstalled -#UseDelta = 0.7 Architecture = auto -# Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup -#IgnorePkg = -#IgnoreGroup = - -#NoUpgrade = -#NoExtract = - -# Misc options -#UseSyslog Color -ILoveCandy -#NoProgressBar -#CheckSpace +CheckSpace VerbosePkgLists +ParallelDownloads = 5 DisableDownloadTimeout -ParallelDownloads = 10 -DownloadUser = alpm -#DisableSandbox -# By default, pacman accepts packages signed by keys that its local keyring -# trusts (see pacman-key and its man page), as well as unsigned packages. SigLevel = Required DatabaseOptional LocalFileSigLevel = Optional -#RemoteFileSigLevel = Required - -# NOTE: You must run `pacman-key --init` before first using pacman; the local -# keyring can then be populated with the keys of all official Arch Linux -# packagers with `pacman-key --populate archlinux`. # # REPOSITORIES -# - can be defined here or included from another file -# - pacman will search repositories in the order defined here -# - local/custom mirrors can be added here or in separate files -# - repositories listed first will take precedence when packages -# have identical names, regardless of version number -# - URLs will have $repo replaced by the name of the current repo -# - URLs will have $arch replaced by the name of the architecture -# -# Repository entries are of the format: -# [repo-name] -# Server = ServerName -# Include = IncludePath # -# The header [repo-name] is crucial - it must be present and -# uncommented to enable the repo. +# Arch first, CachyOS last: see the comment in the build-host pacman.conf. +# Here the mirrorlists come from the pacman-mirrorlist and cachyos-mirrorlist +# packages, both of which are installed in SimulationOS. # -[cachyos] -SigLevel = Optional TrustAll -Include = /etc/pacman.d/cachyos-mirrorlist - -# The testing repositories are disabled by default. To enable, uncomment the -# repo name header and Include lines. You can add preferred servers immediately -# after the header, and they will be used before the default mirrors. - -#[core-testing] -#Include = /etc/pacman.d/mirrorlist - [core] Include = /etc/pacman.d/mirrorlist -#[extra-testing] -#Include = /etc/pacman.d/mirrorlist - [extra] Include = /etc/pacman.d/mirrorlist -# If you want to run 32 bit applications on your x86_64 system, -# enable the multilib repositories as required here. - -#[multilib-testing] -#Include = /etc/pacman.d/mirrorlist - [multilib] Include = /etc/pacman.d/mirrorlist -# An example of a custom package repository. See the pacman manpage for -# tips on creating your own repositories. -#[custom] -#SigLevel = Optional TrustAll -#Server = file:///home/custompkgs +[cachyos] +Include = /etc/pacman.d/cachyos-mirrorlist diff --git a/airootfs/etc/pacman.d/mirrorlist b/airootfs/etc/pacman.d/mirrorlist deleted file mode 100644 index 4e41670..0000000 --- a/airootfs/etc/pacman.d/mirrorlist +++ /dev/null @@ -1,11 +0,0 @@ -# CachyOS's Mirror -# Force good mirrors for installation -# Mirrors from india currently being reported as fully synced but they are not -# CachyOS provdes a CDN Cache archlinux mirror -# as fallback an alternative cloudflare mirror will be used -# as third fallback GEO mirrors from archlinux will be used -Server = https://archlinux.cachyos.org/repo/$repo/os/$arch -Server = https://geo.mirror.pkgbuild.com/$repo/os/$arch -Server = https://build-1.cachyos.org/archlinux/$repo/os/$arch -Server = https://mirror.rackspace.com/archlinux/$repo/os/$arch -Server = http://mirror.rackspace.com/archlinux/$repo/os/$arch diff --git a/airootfs/etc/polkit-1/49-nopasswd_global.rules b/airootfs/etc/polkit-1/49-nopasswd_global.rules deleted file mode 100644 index afc8670..0000000 --- a/airootfs/etc/polkit-1/49-nopasswd_global.rules +++ /dev/null @@ -1,9 +0,0 @@ -/* Allow members of the wheel group to execute any actions - * without password authentication, similar to "sudo NOPASSWD:" - */ -polkit.addRule(function(action, subject) { - if (subject.isInGroup("wheel")) { - return polkit.Result.YES; - } -}); - diff --git a/airootfs/etc/polkit-1/rules.d/49-simulationos-live-nopasswd.rules b/airootfs/etc/polkit-1/rules.d/49-simulationos-live-nopasswd.rules new file mode 100644 index 0000000..09bdabf --- /dev/null +++ b/airootfs/etc/polkit-1/rules.d/49-simulationos-live-nopasswd.rules @@ -0,0 +1,10 @@ +/* SimulationOS live medium only. + * Lets the live user run the installer and disk tools without a password + * prompt, because the live account has no password to type. + * Removed from the installed system by simulationos-deloop. + */ +polkit.addRule(function(action, subject) { + if (subject.isInGroup("wheel")) { + return polkit.Result.YES; + } +}); diff --git a/airootfs/etc/polkit-1/rules.d/sddm.conf.d/autologin.conf b/airootfs/etc/polkit-1/rules.d/sddm.conf.d/autologin.conf deleted file mode 100644 index 9acf8bf..0000000 --- a/airootfs/etc/polkit-1/rules.d/sddm.conf.d/autologin.conf +++ /dev/null @@ -1,15 +0,0 @@ -[Autologin] -Relogin=false -Session=hyprland -User=liveuser - -[General] -HaltCommand=/usr/bin/systemctl poweroff -RebootCommand=/usr/bin/systemctl reboot - -[Theme] -Current=breeze - -[Users] -MaximumUid=60000 -MinimumUid=1000 diff --git a/airootfs/etc/resolv.conf b/airootfs/etc/resolv.conf deleted file mode 120000 index 3639662..0000000 --- a/airootfs/etc/resolv.conf +++ /dev/null @@ -1 +0,0 @@ -/run/systemd/resolve/stub-resolv.conf \ No newline at end of file diff --git a/airootfs/etc/sddm.conf.d/10-simulationos.conf b/airootfs/etc/sddm.conf.d/10-simulationos.conf new file mode 100644 index 0000000..4603b79 --- /dev/null +++ b/airootfs/etc/sddm.conf.d/10-simulationos.conf @@ -0,0 +1,9 @@ +[General] +DisplayServer=x11 + +[Theme] +Current=maldives + +[Users] +RememberLastUser=true +RememberLastSession=true diff --git a/airootfs/etc/sddm.conf.d/20-simulationos-live-autologin.conf b/airootfs/etc/sddm.conf.d/20-simulationos-live-autologin.conf new file mode 100644 index 0000000..7f8c9fd --- /dev/null +++ b/airootfs/etc/sddm.conf.d/20-simulationos-live-autologin.conf @@ -0,0 +1,6 @@ +# SimulationOS live medium only. +# Removed from the installed system by simulationos-deloop. +[Autologin] +User=liveuser +Session=hyprland.desktop +Relogin=false diff --git a/airootfs/etc/simulationos-release b/airootfs/etc/simulationos-release index 3b17094..25af5aa 100644 --- a/airootfs/etc/simulationos-release +++ b/airootfs/etc/simulationos-release @@ -1,4 +1,5 @@ LSB_VERSION=1.0 DISTRIB_ID=SimulationOS DISTRIB_RELEASE=rolling -DISTRIB_DESCRIPTION="SimulationOS Linux" +DISTRIB_CODENAME=alpha +DISTRIB_DESCRIPTION="SimulationOS Alpha" diff --git a/airootfs/etc/skel/.bashrc b/airootfs/etc/skel/.bashrc index 3f9e3b9..68c9ada 100644 --- a/airootfs/etc/skel/.bashrc +++ b/airootfs/etc/skel/.bashrc @@ -1,125 +1,91 @@ # -# ~/.bashrc +# ~/.bashrc - SimulationOS +# +# Every alias here refers to a command that SimulationOS actually installs. +# The previous version aliased `rm` to trash-put and used nvim/nvidia-smi/ +# snapper/auto-cpufreq without shipping any of them, which broke `rm` in the +# live session. # # If not running interactively, don't do anything [[ $- != *i* ]] && return -# Change the window title PS1='[\u@\h \W]\$ ' [ -r /usr/share/bash-completion/bash_completion ] && . /usr/share/bash-completion/bash_completion -# Export export EDITOR='nvim' export VISUAL='nvim' export HISTCONTROL=ignoreboth:erasedups -#ignore upper and lowercase when TAB completion -bind "set completion-ignore-case on" - -#system -alias edital='$EDITOR ~/.bashrc' -alias applyal='source ~/.bashrc' -alias please='sudo' - - +# ignore case during TAB completion +bind "set completion-ignore-case on" 2>/dev/null +# ------------------------------------------------------------------- listing +alias ls='eza --color=always --group-directories-first --icons' alias l='eza --color=always --group-directories-first --icons' -alias l.='eza -a | grep -e '\''^\.'\''' alias la='eza -al --color=always --group-directories-first --icons' alias ll='eza -l --color=always --group-directories-first --icons' -alias ls='eza -a --color=always --group-directories-first --icons' alias lt='eza -aT --color=always --group-directories-first --icons' + +# ------------------------------------------------------------------- general alias grep='grep --colour=auto' -alias egrep='egrep --colour=auto' -alias fgrep='fgrep --colour=auto' -alias df='df -h' # human-readable sizes -alias free='free -m' -alias c="clear" -alias n="nvim" -alias ex="exit" -alias fs="fastfetch" -alias nv='nvidia-smi' +alias df='df -h' +alias du='du -h --max-depth=1' +alias free='free -m' +alias c='clear' +alias n='nvim' +alias fs='fastfetch' alias ..='cd ..' alias ...='cd ../..' alias ....='cd ../../..' -alias .....='cd ../../../..' - -# git -alias du='du -h --max-depth=1' +# ----------------------------------------------------------------------- git +alias gs='git status' +alias ga='git add' alias gc='git commit -m' alias gco='git checkout' alias gb='git branch' alias gd='git diff' -alias ga='git add' -alias gs='git status' -alias gp='git push' -alias gpm='git push origin main' -alias gl='git pull' -alias gn='git clone' -alias gpr='git pull --rebase' -#newtworks -alias ports='netstat -tulanp' - -#pacman -alias belong='sudo pacman -Qo' +# -------------------------------------------------------------------- pacman alias in='sudo pacman -S' -alias qu='sudo pacman -Sii' alias re='sudo pacman -Rs' +alias up='sudo pacman -Syu' alias search='pacman -Ss' -alias up='sudo pacman -Syyu' +alias belong='pacman -Qo' -#etc -alias kernel='ls /usr/lib/modules' +# --------------------------------------------------------------- SimulationOS +alias install-simulationos='simulationos-install' alias kernels='ls /usr/lib/modules' -alias rm='trash-put' -alias snapchome='sudo snapper -c home create-config /home' -alias snapcroot='sudo snapper -c root create-config /' -alias sound='pavucontrol' - -ex () -{ - if [ -f $1 ] ; then - case $1 in - *.tar.bz2) tar xjf $1 ;; - *.tar.gz) tar xzf $1 ;; - *.bz2) bunzip2 $1 ;; - *.rar) unrar x $1 ;; - *.gz) gunzip $1 ;; - *.tar) tar xf $1 ;; - *.tbz2) tar xjf $1 ;; - *.tgz) tar xzf $1 ;; - *.zip) unzip $1 ;; - *.Z) uncompress $1;; - *.7z) 7z x $1 ;; - *.deb) ar x $1 ;; - *.tar.xz) tar xf $1 ;; - *.tar.zst) tar xf $1 ;; - *) echo "'$1' cannot be extracted via ex()" ;; - esac - else - echo "'$1' is not a valid file" +# extract almost anything +extract() { + if [ ! -f "$1" ]; then + printf 'extract: %s is not a valid file\n' "$1" >&2 + return 1 fi + case "$1" in + *.tar.bz2|*.tbz2) tar xjf "$1" ;; + *.tar.gz|*.tgz) tar xzf "$1" ;; + *.tar.xz|*.tar.zst|*.tar) tar xf "$1" ;; + *.bz2) bunzip2 "$1" ;; + *.gz) gunzip "$1" ;; + *.zip) unzip "$1" ;; + *.7z) 7z x "$1" ;; + *) printf 'extract: unsupported archive %s\n' "$1" >&2; return 1 ;; + esac } -# Bash won't get SIGWINCH if another process is in the foreground. -# Enable checkwinsize so that bash will check the terminal size when -# it regains control. #65623 -# http://cnswww.cns.cwru.edu/~chet/bash/FAQ (E11) shopt -s checkwinsize - -#beautiful stuff -shopt -s autocd # change to named directory -shopt -s cdspell # autocorrects cd misspellings -shopt -s cmdhist # save multi-line commands in history as single line -shopt -s dotglob -shopt -s histappend # do not overwrite history -shopt -s expand_aliases # expand aliases - - - -#fastfetch +shopt -s autocd +shopt -s cdspell +shopt -s cmdhist +shopt -s histappend +shopt -s expand_aliases + +# Short system summary on the first interactive shell of a session. +if [ -z "$SIMOS_FETCH_SHOWN" ] && [ -t 1 ]; then + export SIMOS_FETCH_SHOWN=1 + command -v fastfetch >/dev/null 2>&1 && fastfetch +fi diff --git a/airootfs/etc/skel/.config/hypr/config/.jukit/.jukit_info.json b/airootfs/etc/skel/.config/hypr/config/.jukit/.jukit_info.json deleted file mode 100755 index 92c7342..0000000 --- a/airootfs/etc/skel/.config/hypr/config/.jukit/.jukit_info.json +++ /dev/null @@ -1 +0,0 @@ -{"terminal": "nvimterm"} \ No newline at end of file diff --git a/airootfs/etc/skel/.config/hypr/config/animations.conf b/airootfs/etc/skel/.config/hypr/config/animations.conf deleted file mode 100755 index a6993aa..0000000 --- a/airootfs/etc/skel/.config/hypr/config/animations.conf +++ /dev/null @@ -1,37 +0,0 @@ -# ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ -# ┃ Animations Configuration ┃ -# ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - -# https://wiki.hyprland.org/0.45.0/Configuring/Animations/ - -animations { - enabled = yes - bezier = overshot, 0.13, 0.99, 0.29, 1.1 - # animation = windowsIn, 1, 4, overshot, slide - # animation = windowsOut, 1, 5, default, popin 80% - # animation = border, 1, 5, default - # animation = workspacesIn, 1, 6, overshot, slide - # animation = workspacesOut, 1, 6, overshot, slidefade 80% - - - bezier = linear, 0, 0, 1, 1 - bezier = md3_standard, 0.2, 0, 0, 1 - bezier = md3_decel, 0.05, 0.7, 0.1, 1 - bezier = md3_accel, 0.3, 0, 0.8, 0.15 - bezier = overshot_alt, 0.05, 0.9, 0.1, 1.1 - bezier = hyprnostretch, 0.05, 0.9, 0.1, 1.0 - bezier = menu_decel, 0.1, 1, 0, 1 - bezier = menu_accel, 0.38, 0.04, 1, 0.07 - - # Animation configs - balanced between aesthetics and speed - animation = windows, 1, 3, md3_decel, popin 60% - animation = windowsIn, 1, 3, md3_decel, popin 60% - animation = windowsOut, 1, 3, md3_accel, popin 60% - animation = border, 1, 5, default - animation = fade, 1, 3, md3_decel - animation = layersIn, 1, 3, menu_decel, slide - animation = layersOut, 1, 1.6, menu_accel - animation = fadeLayersIn, 1, 2, menu_decel - animation = fadeLayersOut, 1, 0.5, menu_accel - animation = workspaces, 1, 3, md3_decel, slide -} diff --git a/airootfs/etc/skel/.config/hypr/config/autostart.conf b/airootfs/etc/skel/.config/hypr/config/autostart.conf deleted file mode 100755 index f28172a..0000000 --- a/airootfs/etc/skel/.config/hypr/config/autostart.conf +++ /dev/null @@ -1,87 +0,0 @@ -# ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ -# ┃ Autostart Configuration ┃ -# ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - -source = ~/.config/hypr/config/defaults.conf -#exec-once = python ~/.scripts/Acer/predator-handler.py -# Autostart wiki https://wiki.hyprland.org/0.45.0/Configuring/Keywords/#executing # - -#exec-once = swaybg -o \* -i /usr/share/wallpapers/cachyos-wallpapers/BlueFeathers.png -m fill -#exec-once = hyprpaper -exec-once = swww-daemon -exec-once = swww img /mnt/m.2_ssd/Linux/Wallpapers/1354205.jpeg -exec-once = waybar & -#exec-once = fcitx5 -d & -exec-once = brightnessctl set 0% -#exec-once = mako & -exec-once = swaync & -exec-once = nm-applet --indicator & - -#exec-once = bash -c "mkfifo /tmp/$HYPRLAND_INSTANCE_SIGNATURE.wob && tail -f /tmp/$HYPRLAND_INSTANCE_SIGNATURE.wob | wob -c ~/.config/hypr/wob.ini & disown" & - -exec-once = /usr/lib/polkit-kde-authentication-agent-1 & -#exec-once = hypridle -exec-once = ~/.config/hypr/scripts/mic-default-volume.sh -#exec-once = ~/.scripts/hyprland/sound-conig.sh - -# ## Slow app launch fix -exec-once = systemctl --user import-environment & -exec-once = hash dbus-update-activation-environment 2>/dev/null & -exec-once = dbus-update-activation-environment --systemd & -exec-once = ~/.scripts/Acer/PredatorSense/rgbkb/rgbkb.service.sh - -# ## Idle configuration -#exec-once = $idlehandler -#exec-once = gammastep -l auto -t 5500:3500 -b 1.0:0.8 -#exec-once = gammy & -# -#exec-once = ~/.config/hypr/scripts/light.sh - -#input { -# kb_layout = us,ara -# kb_variant = ,digits - # kb_options = grp:shifts_toggle,caps:swapescape -#} - - -# USER MADE - -# Clipboard -#exec-once = cliphist wipe; wl-paste --watch cliphist store -#exec-once = wl-paste --type text --watch cliphist store # Stores only text data -#exec-once = wl-paste --type image --watch cliphist store # Stores only image data -exec-once = wl-paste --watch cliphist store - - -#exec-once=waypaper --restore - -#env = QT_QPA_PLATFORMTHEME,kde -#env = XDG_MENU_PREFIX,arch- - -# exec-once = /usr/bin/lxqt-policykit-agent -# exec-once = /usr/lib/kdeconnectd -exec-once = kdeconnectd - -#exec-once=walker --gapplication-service # Application Launcher - - -#exec-once = systemctl --user start fan-curve - - - - - - - - - - - - - - - - - - - diff --git a/airootfs/etc/skel/.config/hypr/config/colors.conf b/airootfs/etc/skel/.config/hypr/config/colors.conf deleted file mode 100755 index 1a150bd..0000000 --- a/airootfs/etc/skel/.config/hypr/config/colors.conf +++ /dev/null @@ -1,146 +0,0 @@ -# ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ -# ┃ Colors Configuration ┃ -# ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - -#$cachylgreen = rgba(82dcccff) -#$cachymgreen = rgba(00aa84ff) -#$cachydgreen = rgba(007d6fff) -#$cachylblue = rgba(01ccffff) -#$cachymblue = rgba(182545ff) -#$cachydblue = rgba(111826ff) -#$cachywhite = rgba(ffffffff) -#$cachygrey = rgba(ddddddff) -#$cachygray = rgba(798bb2ff) -#$kararwallpaper = rgba(f58f29ff) -#$kararwallpaper = rgba(e8aa3aff) - - - - - - - - - - - - -# ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ -# ┃ Colors Configuration ┃ -# ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - -# Your custom accent colors -$cachylgreen = rgba(82dcccff) -$cachymgreen = rgba(00aa84ff) -$cachydgreen = rgba(007d6fff) -$cachylblue = rgba(01ccffff) -$cachymblue = rgba(182545ff) -$cachydblue = rgba(111826ff) -$cachywhite = rgba(ffffffff) -$cachygrey = rgba(ddddddff) -$cachygray = rgba(798bb2ff) - -$kararwallpaper = rgba(e8aa3aff) - -# Extended color palette for UI and theming -$background = rgba(18120cff) - -$error = rgba(ffb4abff) - -$error_container = rgba(93000aff) - -$inverse_on_surface = rgba(372f27ff) - -$inverse_primary = rgba(825513ff) - -$inverse_surface = rgba(eee0d4ff) - -$on_background = rgba(eee0d4ff) - -$on_error = rgba(690005ff) - -$on_error_container = rgba(ffdad6ff) - -$on_primary = rgba(472a00ff) - -$on_primary_container = rgba(ffddb7ff) - -$on_primary_fixed = rgba(2a1700ff) - -$on_primary_fixed_variant = rgba(653e00ff) - -$on_secondary = rgba(3f2d17ff) - -$on_secondary_container = rgba(fcddbcff) - -$on_secondary_fixed = rgba(281805ff) - -$on_secondary_fixed_variant = rgba(57432bff) - -$on_surface = rgba(eee0d4ff) - -$on_surface_variant = rgba(d4c4b5ff) - -$on_tertiary = rgba(273513ff) - -$on_tertiary_container = rgba(d7e9b9ff) - -$on_tertiary_fixed = rgba(121f02ff) - -$on_tertiary_fixed_variant = rgba(3c4c28ff) - -$outline = rgba(9c8e80ff) - -$outline_variant = rgba(504539ff) - -$primary = rgba(f7bb71ff) - -$primary_container = rgba(653e00ff) - -$primary_fixed = rgba(ffddb7ff) - -$primary_fixed_dim = rgba(f7bb71ff) - -$scrim = rgba(000000ff) - -$secondary = rgba(dfc2a2ff) - -$secondary_container = rgba(57432bff) - -$secondary_fixed = rgba(fcddbcff) - -$secondary_fixed_dim = rgba(dfc2a2ff) - -$shadow = rgba(000000ff) - -$source_color = rgba(c58012ff) - -$surface = rgba(18120cff) - -$surface_bright = rgba(403830ff) - -$surface_container = rgba(251e17ff) - -$surface_container_high = rgba(302921ff) - -$surface_container_highest = rgba(3b332bff) - -$surface_container_low = rgba(211a13ff) - -$surface_container_lowest = rgba(130d07ff) - -$surface_dim = rgba(18120cff) - -$surface_tint = rgba(f7bb71ff) - -$surface_variant = rgba(504539ff) - -$tertiary = rgba(bbcd9eff) - -$tertiary_container = rgba(3c4c28ff) - -$tertiary_fixed = rgba(d7e9b9ff) - -$tertiary_fixed_dim = rgba(bbcd9eff) - - diff --git a/airootfs/etc/skel/.config/hypr/config/decorations.conf b/airootfs/etc/skel/.config/hypr/config/decorations.conf deleted file mode 100755 index 8707190..0000000 --- a/airootfs/etc/skel/.config/hypr/config/decorations.conf +++ /dev/null @@ -1,97 +0,0 @@ -# ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ -# ┃ Decorations Configuration ┃ -# ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - -#source = ~/.config/hypr/config/colors.conf - -# https://wiki.hyprland.org/0.45.0/Configuring/Variables/#decoration - -#decoration { -# active_opacity = 1 -# rounding = 4 - - # https://wiki.hyprland.org/0.45.0/Configuring/Variables/#blur -# blur { -# size = 15 -# passes = 2 # more passes = more resource intensive. -# xray = true -# } -# -# # https://wiki.hyprland.org/0.45.0/Configuring/Variables/#shadow -# shadow { -# enabled = true -# } -# -#} - - - - # ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ -# ┃ Decorations Configuration ┃ -# ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - -source = ~/.config/hypr/config/colors.conf - -decoration { - rounding = 8 - active_opacity = 1 - - # ── Blur Settings ────────────────────────────────────────── - blur { - enabled = true - xray = true # May be disabled for performance if needed - special = true - new_optimizations = true - size = 8 - passes = 1 - brightness = 2.0 - noise = 0.20 - contrast = 0.70 - popups = false - popups_ignorealpha = 0.6 - - # PERFORMANCE ADDITIONS: - ignore_opacity = true # Better performance with transparent windows - vibrancy = 0.0 # Disable vibrancy effects - vibrancy_darkness = 0.0 # Disable vibrancy darkness - } - - # ── Shadow Settings ──────────────────────────────────────── - shadow { - enabled = true - ignore_window = true - range = 12 - offset = 0 2 - render_power = 2 - color = rgba(0000002A) - - # PERFORMANCE ADDITIONS: - sharp = false # Soft shadows are faster - } - - # ── Inactive Dimming ─────────────────────────────────────── - dim_inactive = true - dim_strength = 0.1 - dim_special = 0 - - # ── Opacity (uncomment if needed) ────────────────────────── - inactive_opacity = 1 - fullscreen_opacity = 1 - - # ── Optional Shaders ─────────────────────────────────────── - # screen_shader = ~/.config/hypr/shaders/nothing.frag - # screen_shader = ~/.config/hypr/shaders/vibrance.frag -} - -layerrule = blur, swaync-control-center -layerrule = ignorezero, swaync-notification-window -layerrule = animation slide right, swaync-control-center - -layerrule = blur, swaync-control-center -layerrule = blur, swaync-notification-window - -layerrule = ignorezero, swaync-control-center -layerrule = ignorezero, swaync-notification-window - -layerrule = ignorealpha 0.5, swaync-control-center -layerrule = ignorealpha 0.5, swaync-notification-window diff --git a/airootfs/etc/skel/.config/hypr/config/defaults.conf b/airootfs/etc/skel/.config/hypr/config/defaults.conf deleted file mode 100755 index 7a5a2e6..0000000 --- a/airootfs/etc/skel/.config/hypr/config/defaults.conf +++ /dev/null @@ -1,71 +0,0 @@ -# ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ -# ┃ Defaults Configuration ┃ -# ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - - -# ── File Manager (Performance Choice) ────────────────────────── -# Option 1: Lightweight (fastest) -#$filemanager = thunar # Lighter than dolphin -# Option 2: Current (moderate performance) - $filemanager = dolphin --platformtheme kde - -# ── Browser (Performance Choice) ─────────────────────────────── -$browser = firefox # Good choice for performance - -# ── App Launcher (Performance Optimized) ─────────────────────── -# Simplified rofi without heavy themes -#$applauncher = rofi -show drun -no-plugins # Faster startup -# Or your current themed version (slightly slower but prettier) -$applauncher = rofi -show drun -theme ~/.config/rofi/launchers/type-3/style-5.rasi - -# ── Terminal (Performance Choice) ────────────────────────────── -# Current kitty is already fast -$terminal = kitty -# Alternative lightweight options: -# $terminal = foot # Faster startup -# $terminal = alacritty # Also very fast - -# ── Screen Capture (Optimized) ───────────────────────────────── -# Simpler capture without swappy for speed -#$capturing = grim -g "$(slurp)" ~/Pictures/screenshot-$(date +%Y%m%d_%H%M%S).png -$capturing = grimblast --freeze save area - | satty --filename - --copy-command wl-copy --save-after-copy --early-exit --init-tool brush -# Or keep your current with swappy (slower but more features) -# $capturing = grim -g "$(slurp)" - | swappy -f - - -# ── Clipboard (Performance Optimized) ────────────────────────── -# Simplified clipboard without images for speed -#$clip = cliphist list | rofi -dmenu -p "Clipboard" | cliphist decode | wl-copy -# Or keep your current with icons (slower but prettier) -$clip = rofi -modi clipboard:~/.local/bin/cliphist-rofi-img -show clipboard -show-icons -theme ~/.config/rofi/launchers/type-3/clipboard.rasi - -# ── PDF Viewer (Performance Choice) ──────────────────────────── -# Lighter alternatives to okular -#$pdfviewer = zathura # Much faster than okular -# Or keep okular if you need the features -$pdfviewer = okular --platformtheme kde - -# ── Additional Performance Variables ─────────────────────────── - - - -# Screenshots -#$shot-region = grimblast copy area -#$shot-window = grimblast copy active -#$shot-screen = grimblast copy output - - - -# OLD -#$filemanager = dolphin --platformtheme kde -#$browser = cachy-browser -#$browser = firefox -#$applauncher = rofi -show combi -modi window,run,combi -combi-modi window,run -#$applauncher = rofi -show drun -#$applauncher = rofi -show drun -theme ~/.config/rofi/launchers/type-3/style-5.rasi -#$terminal = kitty -#$idlehandler = swayidle -w timeout 300 'swaylock -f -c 000000' before-sleep 'swaylock -f -c 000000' -#$capturing = grim -g "$(slurp)" - | swappy -f - -#$power = ~/.config/rofi/powermenu/type-2/powermenu.sh -#$clip = rofi -modi clipboard:~/.local/bin/cliphist-rofi-img -show clipboard -show-icons -theme ~/.config/rofi/launchers/type-3/clipboard.rasi -#$clip = cliphist list | rofi -modi clipboard -show clipboard -theme ~/.config/rofi/launchers/type-3/clipboard.rasi -dmenu | cliphist decode | wl-copy -#$pdfviewer = okular --platformtheme kde diff --git a/airootfs/etc/skel/.config/hypr/config/environment.conf b/airootfs/etc/skel/.config/hypr/config/environment.conf deleted file mode 100755 index c105622..0000000 --- a/airootfs/etc/skel/.config/hypr/config/environment.conf +++ /dev/null @@ -1,108 +0,0 @@ -# ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ -# ┃ Enviroment Configuration ┃ -# ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - -envd = HYPRCURSOR_SIZE,24 -envd = XCURSOR_SIZE,24 -envd = QT_CURSOR_SIZE,24 -env = GTK_USE_PORTAL,1 -env = HYPRCURSOR_SIZE,24 -# ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ -# ┃ Environment Configuration ┃ -# ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - -# ── Cursor Sizes ────────────────────────────────────────────── -#envd = HYPRCURSOR_SIZE,24 -#envd = XCURSOR_SIZE,24 -#envd = QT_CURSOR_SIZE,24 -env = XCURSOR_SIZE,24 # In case apps ignore envd - -# ── Input Methods ───────────────────────────────────────────── -# I don't use fcitx - -#env = QT_IM_MODULE,fcitx -#env = XMODIFIERS,@im=fcitx -#env = SDL_IM_MODULE,fcitx -#env = GLFW_IM_MODULE,ibus -#env = INPUT_METHOD,fcitx - -# ── Virtual Environment (AGS) ───────────────────────────────── -env = ILLOGICAL_IMPULSE_VIRTUAL_ENV,~/.local/state/ags/.venv - -# ── Wayland / Desktop Session ───────────────────────────────── -#env = XDG_CURRENT_DESKTOP,KDE -#env = XDG_SESSION_TYPE,wayland -#env = XDG_SESSION_DESKTOP,Hyprland - -env = XDG_CURRENT_DESKTOP,Hyprland -env = XDG_SESSION_DESKTOP,Hyprland -env = XDG_SESSION_TYPE,wayland - -env = QT_QPA_PLATFORM,wayland -env = QT_QPA_PLATFORMTHEME,qt6ct -#env = QT_STYLE_OVERRIDE,kvantum -#env = QT_QPA_PLATFORMTHEME,qt5ct -#env = QT_QPA_PLATFORMTHEME,qt6ct -env = XDG_MENU_PREFIX,arch- - -#env = QT_QPA_PLATFORMTHEME,kde -#env = XDG_MENU_PREFIX,plasma- - - -# ── QT Configuration ────────────────────────────────────────── -#env = QT_QPA_PLATFORM,wayland;xcb -#env = QT_QPA_PLATFORMTHEME,qt6ct -env = QT_WAYLAND_DISABLE_WINDOWDECORATION,1 -#env = QT_AUTO_SCREEN_SCALE_FACTOR,1 - -#env = QT_QPA_PLATFORMTHEME,qt6ct -#env = QT_QPA_PLATFORM,wayland -#env = QT_STYLE_OVERRIDE,Breeze - - -# ── GTK Configuration ───────────────────────────────────────── -#env = GDK_SCALE,1 - -#env = GTK_THEME,Breeze-Dark - -# ── Mozilla (Wayland support) ───────────────────────────────── -env = MOZ_ENABLE_WAYLAND,1 - -# Performance additions: -env = MOZ_WEBRENDER,1 # Enable hardware acceleration -env = MOZ_X11_EGL,1 # Better GPU acceleration - -# ── AppImage Launcher ───────────────────────────────────────── -env = APPIMAGELAUNCHER_DISABLE,1 - -# ── Ozone Platform ──────────────────────────────────────────── -env = OZONE_PLATFORM,wayland - -# ── Optional for Virtual Machines (commented) ───────────────── - env = WLR_NO_HARDWARE_CURSORS,1 - env = WLR_RENDERER_ALLOW_SOFTWARE,1 -# ── Optional NVIDIA Support (commented) ─────────────────────── - env = LIBVA_DRIVER_NAME,nvidia - env = GBM_BACKEND,nvidia-drm - env = __GLX_VENDOR_LIBRARY_NAME,nvidia - env = __GL_VRR_ALLOWED,1 -# env = WLR_DRM_NO_ATOMIC,1 - -env = __GL_VRR_ALLOWED,1 # Enable VRR for smoother experience -env = WLR_RENDERER_ALLOW_SOFTWARE,1 # Fallback option - -# ── Memory/CPU Performance ──────────────────────────────────── -#env = MALLOC_TRIM_THRESHOLD_,100000 # Better memory management -#env = MALLOC_MMAP_THRESHOLD_,131072 # Memory optimization - -# ── Disable Heavy Features ──────────────────────────────────── -# env = GTK_USE_PORTAL,1 # Commented out - portals can be slow -# env = QT_AUTO_SCREEN_SCALE_FACTOR,1 # Disable auto scaling - -# ── GPU USAGE ──────────────────────────────────── -#env = AQ_DRM_DEVICES,/dev/dri/card1:/dev/dri/card0 - -# ── ROFI Clipbaord ──────────────────────────────────── - -env = CLIPHIST_MAX_ITEMS=25 - diff --git a/airootfs/etc/skel/.config/hypr/config/fan_curve.json b/airootfs/etc/skel/.config/hypr/config/fan_curve.json deleted file mode 100755 index c9f2f00..0000000 --- a/airootfs/etc/skel/.config/hypr/config/fan_curve.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "cpu_curve": [ - { - "temp": 35, - "fan": 20 - }, - { - "temp": 50, - "fan": 35 - }, - { - "temp": 65, - "fan": 50 - }, - { - "temp": 75, - "fan": 70 - }, - { - "temp": 85, - "fan": 85 - }, - { - "temp": 95, - "fan": 100 - } - ], - "gpu_curve": [ - { - "temp": 40, - "fan": 25 - }, - { - "temp": 55, - "fan": 40 - }, - { - "temp": 70, - "fan": 55 - }, - { - "temp": 80, - "fan": 75 - }, - { - "temp": 90, - "fan": 90 - }, - { - "temp": 100, - "fan": 100 - } - ], - "hysteresis": 3, - "update_interval": 2 -} \ No newline at end of file diff --git a/airootfs/etc/skel/.config/hypr/config/input.conf b/airootfs/etc/skel/.config/hypr/config/input.conf deleted file mode 100755 index 71c838d..0000000 --- a/airootfs/etc/skel/.config/hypr/config/input.conf +++ /dev/null @@ -1,82 +0,0 @@ -# ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ -# ┃ Input Configuration ┃ -# ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - -# Input wiki https://wiki.hyprland.org/0.45.0/Configuring/Variables/#input - -# Invert touchoad scrolling -input { - touchpad { - natural_scroll = true - - disable_while_typing = true - clickfinger_behavior = true - } -} - -input { - kb_layout = us,ara - kb_variant = , - kb_options=grp:win_space_toggle - numlock_by_default= true - follow_mouse = 1 # 0|1|2|3 - float_switch_override_focus = 2 - repeat_delay = 250 - repeat_rate = 35 - special_fallthrough = true - resolve_binds_by_sym = 1 -# kb_options = grp:shifts_toggle,caps:swapescape -} - - -gestures { - workspace_swipe = true - workspace_swipe_distance = 700 - workspace_swipe_fingers = 4 - workspace_swipe_cancel_ratio = 0.2 - workspace_swipe_min_speed_to_force = 5 - workspace_swipe_direction_lock = true - workspace_swipe_direction_lock_threshold = 10 - workspace_swipe_create_new = true -} - - - -general { - # Gaps and border - gaps_in = 0 - gaps_out = 0 - gaps_workspaces = 0 - border_size = 3 - - # Fallback colors - -col.active_border = rgba(000000FF) # Solid black -col.inactive_border = rgba(00000000) # Fully transparent black - - - resize_on_border = true - no_focus_fallback = true - layout = dwindle - - #focus_to_other_workspaces = true # ahhhh i still haven't properly implemented this - allow_tearing = true # This just allows the `immediate` window rule to work -} - - -misc { - vfr = 1 - vrr = 0 - animate_manual_resizes = false - animate_mouse_windowdragging = false - enable_swallow = false - swallow_regex = (foot|kitty|allacritty|Alacritty) - - disable_hyprland_logo = true - force_default_wallpaper = 0 - new_window_takes_over_fullscreen = 2 - allow_session_lock_restore = true - - disable_splash_rendering = true - initial_workspace_tracking = false -} diff --git a/airootfs/etc/skel/.config/hypr/config/keybinds.conf b/airootfs/etc/skel/.config/hypr/config/keybinds.conf deleted file mode 100755 index 06b317a..0000000 --- a/airootfs/etc/skel/.config/hypr/config/keybinds.conf +++ /dev/null @@ -1,285 +0,0 @@ - -# ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ -# ┃ Keybinds ┃ -# ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - -source = ~/.config/hypr/config/defaults.conf - -# Example: Super + W changes wallpaper -bind = SUPER, print, exec, ~/.config/hypr/scripts/manage_wallpaper.sh - -# Mininize -bind = $mainMod, Z, togglespecialworkspace, magic -bind = $mainMod, Z, movetoworkspace, +0 -bind = $mainMod, Z, togglespecialworkspace, magic -bind = $mainMod, Z, movetoworkspace, special:magic -bind = $mainMod, Z, togglespecialworkspace, magic - - - - - -bindd= SUPER,Z,desc,exec,~/bin/zoomshot.sh -#hyprsunset stuff -bindd = ALT SHIFT, equal, ,exec, hyprctl hyprsunset temperature +500 -bindd = ALT SHIFT, minus, ,exec, hyprctl hyprsunset temperature -500 -bindd = CTRL ALT, equal, ,exec, hyprctl hyprsunset temperature 6500 -bindd = CTRL ALT, minus, ,exec, hyprctl hyprsunset temperature 3000 -# https://wiki.hyprland.org/Configuring/Binds/ -bindd = $mainMod , R, render hypr, exec, hyprctl reload -bindd = $mainMod , B, display or hide the bar, exec, pkill -SIGUSR1 waybar -bindd = $mainMod, RETURN, Opens your preferred terminal emulator ($terminal), exec, $terminal -bindd = $mainMod , SHIFT, power shit, exec, wlogout - -bindd = $mainMod, W, opens cachybrowser, exec, $browser -bindd = $mainMod, R, opens Brave Browser, exec, brave -bindd = $mainMod, E, Opens your preferred filemanager ($filemanager), exec, $filemanager -bindd = $mainMod, A, Screen capture selection, exec, $capturing -bindd = $mainMod, Q, Closes (not kill) current window, killactive, #?? -bindd = $mainMod SHIFT, Q, Exits Hyprland by terminating the user sessions, exec, loginctl terminate-user "" -bindd = $mainMod, M, Switches current window between floating and tiling mode, togglefloating, -bindd = $mainMod, D, Runs your application launcher, exec, $applauncher -bindd = $mainMod, F, Toggles current window fullscreen mode, fullscreen -bindd = $mainMod, Y, Pin current window (shows on all workspaces),pin -bindd = $mainMod ALT, J, Toggles curren window split mode, togglesplit, # dwindle #??bindd = $mainMod, P, powerop, exec, $power -bindd = $mainMod, P, PowerMenu, exec, $power -bindd = $mainMod, V, Clipboard, exec, $clip -bindd = $mainMod SHIFT, V, Wofi Clipboard, exec, ~/.config/hypr/scripts/wofi-clipbaord.sh -# USER MADE -#bind = SUPER+E, exec, dolphin -#bind = SUPER, V, exec, cliphist list | cut -d ' ' -f2- | head -n 20 | rofi -dmenu -i -p "Clipboard" | cliphist decode | wl-copy -#bind = SUPER, V, exec, cliphist list | rofi -dmenu | cliphist decode | wl-copy - - -#bind = , print, exec, grim -g "$(slurp)" - | swappy -f - -o /tmp/swappy_edit.png && wl-copy < /tmp/swappy_edit.png -#bind = , print, exec, grimblast --freeze save area - | satty --filename - --copy-command wl-copy --save-after-copy --early-exit --init-tool brush - -bind = , print, exec, grimblast --freeze save area - | satty --filename - --output-filename ~/Pictures/Screenshots/screenshot-$(date +%Y%m%d_%H%M%S).png --copy-command wl-copy --save-after-copy --early-exit --init-tool brush - -#bind = , print, exec, grim -g "$(slurp)" - | swappy -f - -#bind = SUPER, V, exec, rofi -modi clipboard:~/.local/bin/cliphist-rofi-img -show clipboard -show-icons - -# Volume -# Increase Volume: Right Shift + Up Arrow -# bind = RIGHTSHIFT,up,exec,pamixer --increase 5 -bind = RIGHTSHIFT, up, exec,pactl set-sink-volume @DEFAULT_SINK@ +5% - -# Decrease Volume: Right Shift + Down Arrow -bind = RIGHTSHIFT, down, exec, pamixer --decrease 5 - -# Mute Microphone: F8 -bind = , F8,exec, ~/.config/hypr/scripts/toggle_mic.sh - - -bind = , F5, exec, ~/.config/hypr/scripts/switch_audio.sh - -bind = . SHIFT, F5, exec, ~/.config/hypr/scripts/internal-mic.sh - - -#Turn off Display -bind = SUPER, XF86AudioPlay, exec, ~/.config/hypr/scripts/toggle_display.sh - - -# Rofi -bind = SUPER, TAB, exec, rofi -show window -bind = $mainMod, F11, fullscreen - -#bind = SUPER, X, exec, hyprctl dispatch killactive - - -# ======= Grouping Windows ======= -bindd = $mainMod, T, Toggles current window group mode (ungroup all related), togglegroup, -bindd = $mainMod, Tab, Switches to the next window in the group, changegroupactive, f - -# ======= Toggle Gaps ======= - -bindd = $mainMod SHIFT ,G, Set CachyOS default gaps, exec, hyprctl --batch "keyword general:gaps_out 5;keyword general:gaps_in 3" -bindd = $mainMod, G, Remove gaps between window, exec, hyprctl --batch "keyword general:gaps_out 0;keyword general:gaps_in 0" - -# ======= Volume Control ======= - -bindel = $mainMod SHIFT , equal, exec, pactl set-sink-volume @DEFAULT_SINK@ +5% && pactl get-sink-volume @DEFAULT_SINK@ | grep -oP '\d+(?=%)' | awk '{if($1>100) system("pactl set-sink-volume @DEFAULT_SINK@ 100%")}' # Raise Volume -bindel = $mainMod SHIFT , minus, exec, pactl set-sink-volume @DEFAULT_SINK@ -5% # Lower Volume -bindel = $mainMod SHIFT, M, exec, amixer sset Master toggle | sed -En '/\[on\]/ s/.*\[([0-9]+)%\].*/\1/ p; /\[off\]/ s/.*/0/p' | head -1 > /tmp/$HYPRLAND_INSTANCE_SIGNATURE.wob #Mutes player audio - -# ======= Playback Control ======= - -bindd = , XF86AudioPlay, Toggles play/pause, exec, playerctl play-pause -bindd = , XF86AudioNext, Next track, exec, playerctl next -bindd = , XF86AudioPrev, Previous track, exec, playerctl previous - -# ======= Screen Brightness ======= - -bindel = , XF86MonBrightnessUp, exec, brightnessctl s +5% #Increases brightness 5% -bindel = , XF86MonBrightnessDown, exec, brightnessctl s 5%- #Decreases brightness 5% -#bindd = $mainMod SHIFT, P, Runs the calculator application, exec, gnome-calculator -bindd = $mainMod SHIFT, X, Lock the screen, exec, swaylock-fancy -e -K -p 10 -f Hack-Regular -#bindd = $mainMod, O, Reload/restarts Waybar, exec, killall -SIGUSR2 waybar - -# ======= Window Actions ======= - -## Move window with mainMod + LMB/RMB and dragging -bindd = $mainMod, mouse:272, Move the window towards a direction, movewindow -## Move window towards a direction -bindd = $mainMod SHIFT, left, Move active window to the left, movewindow, l -bindd = $mainMod SHIFT, right, Move active window to the right, movewindow, r -bindd = $mainMod SHIFT, up, Move active window upwards, movewindow, u -bindd = $mainMod SHIFT, down, Move active window downwards, movewindow, d -## Move focus with mainMod + arrow keys -bindd = $mainMod, left, Move focus to the left, movefocus, l -bindd = $mainMod, right, Move focus to the right, movefocus, r -bindd = $mainMod, up, Move focus upwards, movefocus, u -bindd = $mainMod, down, Move focus downwards, movefocus, d -## Resizing windows -# Activate keyboard window resize mode -# https://wiki.hyprland.org/Configuring/Binds/#submaps -bindd = $mainMod SHIFT, R, Activates window resizing mode, submap, resize -submap = resize -bindd = , right, Resize to the right (resizing mode), resizeactive, 15 0 -bindd = , left, Resize to the left (resizing mode), resizeactive, -15 0 -bindd = , up, Resize upwards (resizing mode), resizeactive, 0 -15 -bindd = , down, Resize downwards (resizing mode), resizeactive, 0 15 -bindd = , l, Resize to the right (resizing mode), resizeactive, 15 0 -bindd = , h, Resize to the left (resizing mode), resizeactive, -15 0 -bindd = , k, Resize upwards (resizing mode), resizeactive, 0 -15 -bindd = , j, Resize downwards (resizing mode), resizeactive, 0 15 -bindd = , escape, Ends window resizing mode, submap, reset -submap = reset -# Quick resize window with keyboard -# !!! added $mainMod here because CTRL + SHIFT is used for word selection in various text editors -bindd = ALT SHIFT, right, Resize to the right, resizeactive, 15 0 -bindd = ALT SHIFT, left, Resize to the left, resizeactive, -15 0 -bindd = ALT SHIFT, up, Resize upwards, resizeactive, 0 -15 -bindd = ALT SHIFT, down, Resize downwards, resizeactive, 0 15 -bindd = ALT SHIFT, l, Resize to the right, resizeactive, 15 0 -bindd = ALT SHIFT, h, Resize to the left, resizeactive, -15 0 -bindd = ALT SHIFT, k, Resize upwards, resizeactive, 0 -15 -bindd = ALT SHIFT, j, Resize downwards, resizeactive, 0 15 -# Resize window with mainMod + LMB/RMB and dragging -bindm = $mainMod, mouse:273, resizewindow #Resize the window towards a direction -bindm = $mainMod, mouse:272, movewindow #Drag window -## Resizing Windows End # -## Move active window to a workspace with $mainMod + CTRL + [0-9] -bindd = $mainMod SHIFT, 1, Move window and switch to workspace 1, movetoworkspace, 1 -bindd = $mainMod SHIFT, 2, Move window and switch to workspace 2, movetoworkspace, 2 -bindd = $mainMod SHIFT, 3, Move window and switch to workspace 3, movetoworkspace, 3 -bindd = $mainMod SHIFT, 4, Move window and switch to workspace 4, movetoworkspace, 4 -bindd = $mainMod SHIFT, 5, Move window and switch to workspace 5, movetoworkspace, 5 -bindd = $mainMod SHIFT, 6, Move window and switch to workspace 6, movetoworkspace, 6 -bindd = $mainMod SHIFT, 7, Move window and switch to workspace 7, movetoworkspace, 7 -bindd = $mainMod SHIFT, 8, Move window and switch to workspace 8, movetoworkspace, 8 -bindd = $mainMod SHIFT, 9, Move window and switch to workspace 9, movetoworkspace, 9 -bindd = $mainMod SHIFT, 0, Move window and switch to workspace 10, movetoworkspace, 10 -bindd = $mainMod SHIFT, left, Move window and switch to the next workspace, movetoworkspace, -1 -bindd = $mainMod SHIFT, right, Move window and switch to the previous workspace, movetoworkspace, +1 -## Same as above, but doesn't switch to the workspace -bindd = $mainMod CTRL, 1, Move window silently to workspace 1, movetoworkspacesilent, 1 -bindd = $mainMod CTRL, 2, Move window silently to workspace 2, movetoworkspacesilent, 2 -bindd = $mainMod CTRL, 3, Move window silently to workspace 3, movetoworkspacesilent, 3 -bindd = $mainMod CTRL, 4, Move window silently to workspace 4, movetoworkspacesilent, 4 -bindd = $mainMod CTRL, 5, Move window silently to workspace 5, movetoworkspacesilent, 5 -bindd = $mainMod CTRL, 6, Move window silently to workspace 6, movetoworkspacesilent, 6 -bindd = $mainMod CTRL, 7, Move window silently to workspace 7, movetoworkspacesilent, 7 -bindd = $mainMod CTRL, 8, Move window silently to workspace 8, movetoworkspacesilent, 8 -bindd = $mainMod CTRL, 9, Move window silently to workspace 9, movetoworkspacesilent, 9 -bindd = $mainMod CTRL, 0, Move window silently to workspace 10, movetoworkspacesilent, 10 -# Window actions End # - -# ======= Workspace Actions ======= - -# Switch workspaces with mainMod + [0-9] -bindd = $mainMod, 1, Switch to workspace 1, workspace, 1 -bindd = $mainMod, 2, Switch to workspace 2, workspace, 2 -bindd = $mainMod, 3, Switch to workspace 3, workspace, 3 -bindd = $mainMod, 4, Switch to workspace 4, workspace, 4 -bindd = $mainMod, 5, Switch to workspace 5, workspace, 5 -bindd = $mainMod, 6, Switch to workspace 6, workspace, 6 -bindd = $mainMod, 7, Switch to workspace 7, workspace, 7 -bindd = $mainMod, 8, Switch to workspace 8, workspace, 8 -bindd = $mainMod, 9, Switch to workspace 9, workspace, 9 -bindd = $mainMod, 0, Switch to workspace 10, workspace, 10 -# Scroll through existing workspaces with mainMod + , or . -bindd = $mainMod SHIFT, PERIOD, Scroll through workspaces incrementally, workspace, e+1 -bindd = $mainMod SHIFT, COMMA, Scroll through workspaces decrementally, workspace, e-1 -# With $mainMod + scroll -bindd = $mainMod, mouse_down, Scroll through workspaces incrementally, workspace, e+1 -bindd = $mainMod, mouse_up, Scroll through workspaces decrementally, workspace, e-1 -bindd = $mainMod, slash, Switch to the previous workspace, workspace, previous -# Special workspaces (scratchpads) -bindd = $mainMod, PERIOD, Move active window to Special workspace, movetoworkspace,special -bindd = $mainMod, COMMA, Toggles the Special workspace, togglespecialworkspace, special -bindd = $mainMod ALT, 1, Call special workspace scratchpad, togglespecialworkspace, scratchpad -bindd = $mainMod ALT SHIFT, 1, Move active window to special workspace scratchpad, movetoworkspacesilent, special:scratchpad - -# ======= Additional Settings ======= - -# https://wiki.hyprland.org/Configuring/Binds -binds { - allow_workspace_cycles = 1 - workspace_back_and_forth = 1 - workspace_center_on = 1 - movefocus_cycles_fullscreen = true - window_direction_monitor_fallback = true -} - - - -bind = SUPER,X, exec, ~/.config/hypr/scripts/kill-window.sh - -bind = SUPER, KP_End, workspace, 1 -bind = SUPER, KP_Down, workspace, 2 -bind = SUPER, KP_Next, workspace, 3 -bind = SUPER, KP_Left, workspace, 4 -bind = SUPER, KP_Begin, workspace, 5 -bind = SUPER, KP_Right, workspace, 6 -bind = SUPER, KP_Home, workspace, 7 -bind = SUPER, KP_Up, workspace, 8 -bind = SUPER, KP_Prior, workspace, 9 -bind = SUPER, KP_Insert, workspace, 10 -# Move active window to a workspace with numpad + SHIFT + [0-9] -bind = $mainMod SHIFT, KP_End, movetoworkspace, 1 -bind = $mainMod SHIFT, KP_Down, movetoworkspace, 2 -bind = $mainMod SHIFT, KP_Next, movetoworkspace, 3 -bind = $mainMod SHIFT, KP_Left, movetoworkspace, 4 -bind = $mainMod SHIFT, KP_Begin, movetoworkspace, 5 -bind = $mainMod SHIFT, KP_Right, movetoworkspace, 6 -bind = $mainMod SHIFT, KP_Home, movetoworkspace, 7 -bind = $mainMod SHIFT, KP_Up, movetoworkspace, 8 -bind = $mainMod SHIFT, KP_Prior, movetoworkspace, 9 -bind = $mainMod SHIFT, KP_Insert, movetoworkspace, 10 - - - - -bind=,Print,exec,grimblast --freeze copy output - - -bind = SUPER, C, exec, ~/.config/rofi/scripts/rofi-calc.sh -bind = SUPER, S, exec, g4music -bind = SUPER, O, exec, grim -g "$(slurp)" - | tesseract - - -l eng+ara | wl-copy - -bind = ALT, SPACE, exec, nwg-drawer - -# Toggle freeze on active window -#bind = , PAUSE, exec, hyprfreeze -a - -bind = ALT, KP_Insert, exec, hyprfreeze -a - -# SWAYNC -bind = SUPER, N, exec, swaync-client -t - -# Predator Keys -# Mute -bindl=, XF86AudioMute,exec, pactl set-sink-mute @DEFAULT_SINK@ toggle -bindl=, XF86AudioLowerVolume, exec, pactl set-sink-volume @DEFAULT_SINK@ -5% -bindl=, XF86AudioRaiseVolume, exec, pactl set-sink-volume @DEFAULT_SINK@ +5% - -# Toggle_Touchpad -bind = SUPER, F10, exec, ~/.config/hypr/scripts/toggle-touchpad.sh - - -# DRAW -# bind = SUPERALT, G, tooglespecialworkspace, gromit -bind = , F11, exec, gromit-mpx --undo -bind = SHIFT , F11, exec, gromit-mpx --redo -bind = ALT , F11, exec, gromit-mpx --clear diff --git a/airootfs/etc/skel/.config/hypr/config/monitor.conf b/airootfs/etc/skel/.config/hypr/config/monitor.conf deleted file mode 100755 index 187f5e6..0000000 --- a/airootfs/etc/skel/.config/hypr/config/monitor.conf +++ /dev/null @@ -1,20 +0,0 @@ -# ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ -# ┃ Monitor Configuration ┃ -# ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - -# Monitor wiki https://wiki.hyprland.org/0.45.0/Configuring/Monitors/ - -monitor = eDP-2, preferred, 0x0, 1.25 -monitor = HDMI-A-1, preferred, 1920x0, 1 - -#monitor=eDP-2,1920x1080@240.0,0x0,1.0,mirror,eDP-2 -#monitor=HDMI-A-1,1920x1080@74.97,1920x0,1.0,mirror,eDP-2 - - -# If you need to scale things like steam etc, please uncomment these lines. -# Adjust GDK_SCALE accordingly to your liking. -#xwayland { -# force_zero_scaling = true # Unscale XWayland -#} - -#env = GDK_SCALE, 1.25 # GDK Scaling Factor diff --git a/airootfs/etc/skel/.config/hypr/config/user-config.conf b/airootfs/etc/skel/.config/hypr/config/user-config.conf deleted file mode 100755 index 56edba3..0000000 --- a/airootfs/etc/skel/.config/hypr/config/user-config.conf +++ /dev/null @@ -1,14 +0,0 @@ -cursor { - no_hardware_cursors = true -} - -misc { - no_focus_fallback = true - disable_hyprland_urgency = true -} - -misc { - #anr_missed_pings = false - enable_anr_dialog = false -} -misc:vfr = true diff --git a/airootfs/etc/skel/.config/hypr/config/variables.conf b/airootfs/etc/skel/.config/hypr/config/variables.conf deleted file mode 100755 index 75bf704..0000000 --- a/airootfs/etc/skel/.config/hypr/config/variables.conf +++ /dev/null @@ -1,95 +0,0 @@ -# ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ -# ┃ Variables Configuration ┃ -# ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - -source = ~/.config/hypr/config/colors.conf - -# Variables wiki https://wiki.hyprland.org/0.45.0/Configuring/Variables/ # -# https://wiki.hyprland.org/0.45.0/Configuring/Variables/#general -general { - - # ADD THESE FOR PERFORMANCE: - allow_tearing = true # Reduces input lag - resize_on_border = false # Slight performance gain - extend_border_grab_area = 0 # Reduce border calculations - - gaps_in = 2 - gaps_out = 3 - border_size = 1 - col.active_border = $cachylgreen - col.inactive_border = $cachymblue - layout = dwindle # master|dwindle - - # https://wiki.hyprland.org/0.45.0/Configuring/Variables/#snap - snap { - enabled = true - } - -} - -# https://wiki.hyprland.org/0.45.0/Configuring/Variables/#gestures -gestures { - workspace_swipe = true - workspace_swipe_fingers = 4 - workspace_swipe_distance = 250 - workspace_swipe_min_speed_to_force = 15 - workspace_swipe_create_new = false -} - -# https://wiki.hyprland.org/0.45.0/Configuring/Variables/#group -group { - col.border_active = $cachydgreen - col.border_inactive = $cachylgreen - col.border_locked_active = $cachymgreen - col.border_locked_inactive = $cachydblue - - # https://wiki.hyprland.org/0.45.0/Configuring/Variables/#groupbar - groupbar { - font_family = "Fira Sans" - text_color = $cachydblue - col.active = $cachydgreen - col.inactive = $cachylgreen - col.locked_active = $cachymgreen - col.locked_inactive = $cachydblue - } -} -# https://wiki.hyprland.org/0.45.0/Configuring/Variables/#misc -misc { - font_family = "Fira Sans" - splash_font_family = "Fira Sans" - disable_hyprland_logo = true - col.splash = $cachylgreen - background_color = $cachydblue - enable_swallow = true - swallow_regex = ^(firefox|brave|Brave-browser|nautilus|org.kde.dolphin|nemo|thunar|btrfs-assistant.)$ - focus_on_activate = true - vrr = 2 - - # ADD THESE FOR PERFORMANCE: - vfr = true # Variable frame rate - saves power - disable_autoreload = true # Prevent unnecessary reloads - mouse_move_enables_dpms = true # Power saving - key_press_enables_dpms = true # Power saving -} - -# https://wiki.hyprland.org/0.45.0/Configuring/Variables/#render -render { - direct_scanout = true - # ADD THESE FOR PERFORMANCE: -# explicit_sync = 2 # Better GPU sync -# explicit_sync_kms = 2 # Better KMS sync -} - -# See https://wiki.hyprland.org/0.45.0/Configuring/Dwindle-Layout/ for more -dwindle { - special_scale_factor = 0.8 - pseudotile = true # master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below - preserve_split = true -} - -# See https://wiki.hyprland.org/0.45.0/Configuring/Master-Layout/ for more -master { - new_status = master - special_scale_factor = 0.8 - #special_scale_factor = 0.8 -} diff --git a/airootfs/etc/skel/.config/hypr/config/windowrules.conf b/airootfs/etc/skel/.config/hypr/config/windowrules.conf deleted file mode 100755 index a943632..0000000 --- a/airootfs/etc/skel/.config/hypr/config/windowrules.conf +++ /dev/null @@ -1,162 +0,0 @@ -# ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ -# ┃ Windowrules Configuration ┃ -# ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - -# Windows Rules https://wiki.hyprland.org/0.45.0/Configuring/Window-Rules/ # - -# Float Necessary Windows -windowrule = float, class:^Rofi$ -windowrulev2 = float, class:^(org.pulseaudio.pavucontrol) -windowrulev2 = float, class:^()$,title:^(Picture in picture)$ -windowrulev2 = float, class:^()$,title:^(Save File)$ -windowrulev2 = float, class:^()$,title:^(Open File)$ -windowrulev2 = float, class:^(LibreWolf)$,title:^(Picture-in-Picture)$ -windowrulev2 = float, class:^(blueman-manager)$ -windowrulev2 = float, class:^(xdg-desktop-portal-gtk|xdg-desktop-portal-kde|xdg-desktop-portal-hyprland)(.*)$ -windowrulev2 = float, class:^(polkit-gnome-authentication-agent-1|hyprpolkitagent|org.org.kde.polkit-kde-authentication-agent-1)(.*)$ -windowrulev2 = float, class:^(CachyOSHello)$ -windowrulev2 = float, class:^(zenity)$ -windowrulev2 = float, class:^()$,title:^(Steam - Self Updater)$ -# Increase the opacity -windowrulev2 = opacity 0.92, class:^(thunar|nemo|dolphin)$ -windowrulev2 = opacity 0.96, class:^(discord|vesktop|armcord|webcord)$ -windowrulev2 = opacity 0.95, title:^(QQ|Telegram)$ -windowrulev2 = opacity 0.95, title:^(NetEase Cloud Music Gtk4)$ -# General window rules -windowrulev2 = float, title:^(Picture-in-Picture)$ -windowrulev2 = size 960 540, title:^(Picture-in-Picture)$ -windowrulev2 = move 25%-, title:^(Picture-in-Picture)$ -windowrulev2 = float, title:^(imv|mpv|danmufloat|termfloat|nemo|ncmpcpp)$ -windowrulev2 = move 25%-, title:^(imv|mpv|danmufloat|termfloat|nemo|ncmpcpp)$ -windowrulev2 = size 960 540, title:^(imv|mpv|danmufloat|termfloat|nemo|ncmpcpp)$ -windowrulev2 = pin, title:^(danmufloat)$ -windowrulev2 = rounding 5, title:^(danmufloat|termfloat)$ -windowrulev2 = animation slide right, class:^(kitty|Alacritty)$ -windowrulev2 = noblur, class:^(org.mozilla.firefox)$ -windowrulev2 = noblur, class:^(Brave-browser)$ -# Decorations related to floating windows on workspaces 1 to 10 -windowrulev2 = bordersize 2, floating:1, onworkspace:w[fv1-10] -#windowrulev2 = bordercolor $cachylblue, floating:1, onworkspace:w[fv1-10] -#windowrulev2 = bordercolor $kararwallpaper, floating:1, onworkspace:w[fv1-10] -windowrulev2 = rounding 8, floating:1, onworkspace:w[fv1-10] -# Decorations related to tiling windows on workspaces 1 to 10 -windowrulev2 = bordersize 3, floating:0, onworkspace:f[1-10] -windowrulev2 = rounding 4, floating:0, onworkspace:f[1-10] -# Windows Rules End # - -# Workspaces Rules https://wiki.hyprland.org/0.45.0/Configuring/Workspace-Rules/ # -# workspace = 1, default:true, monitor:$priMon -# workspace = 6, default:true, monitor:$secMon -# Workspace selectors https://wiki.hyprland.org/0.45.0/Configuring/Workspace-Rules/#workspace-selectors -# workspace = r[1-5], monitor:$priMon -# workspace = r[6-10], monitor:$secMon -# workspace = special:scratchpad, on-created-empty:$applauncher -# no_gaps_when_only deprecated instead workspaces rules with selectors can do the same -# Smart gaps from 0.45.0 https://wiki.hyprland.org/0.45.0/Configuring/Workspace-Rules/#smart-gaps -workspace = w[tv1-10], gapsout:5, gapsin:3 -workspace = f[1], gapsout:5, gapsin:3 -# Workspaces Rules End # - -# Layers Rules # -layerrule = animation slide top, logout_dialog -# layerrule = animation popin 50%, waybar -layerrule = animation slide down, waybar -layerrule = animation fade 50%, wallpaper -# Layers Rules End # - - - - - - -# General Improvements -windowrulev2 = noblur, xwayland:1 -windowrulev2 = noshadow, floating:0 - -# Dialog windows – center + float common file pickers -windowrulev2 = center, title:^(Open File|Select a File|Choose wallpaper|Open Folder|Save As|Library|File Upload)(.*)$ -windowrulev2 = float, title:^(Open File|Select a File|Choose wallpaper|Open Folder|Save As|Library|File Upload)(.*)$ - -# Picture-in-Picture - improved matching and behavior -windowrulev2 = float, title:^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$ -windowrulev2 = keepaspectratio, title:^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$ -windowrulev2 = move 73% 72%, title:^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$ -windowrulev2 = size 25%, title:^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$ -windowrulev2 = pin, title:^([Pp]icture[-\s]?[Ii]n[-\s]?[Pp]icture)(.*)$ - -# Floating + sizing for settings/connection GUIs -windowrulev2 = float, class:^(nm-connection-editor|pavucontrol|org.pulseaudio.pavucontrol)$ -windowrulev2 = size 45%, class:^(nm-connection-editor|pavucontrol|org.pulseaudio.pavucontrol)$ -windowrulev2 = center, class:^(nm-connection-editor|pavucontrol|org.pulseaudio.pavucontrol)$ -windowrulev2 = float, class:^(steam|blueberry\.py|guifetch)$ - -# Force tiled layout for known apps -windowrulev2 = tile, class:^dev\.warp\.Warp$ - -# Tearing fixes (only if using Wine/Proton games/tools) -windowrulev2 = immediate, title:.*\.exe -windowrulev2 = immediate, class:^(steam_app) - - -windowrulev2 = float,class:gsimplecal -windowrulev2 = size 204 172,class:gsimplecal -windowrulev2 = move 1181 42,class:gsimplecal - - -# KDE FILE PICKER -windowrulev2 = float, class:^(org\.freedesktop\.impl\.portal\.desktop\.kde)$ -windowrulev2 = size 1084 827, class:^(org\.freedesktop\.impl\.portal\.desktop\.kde)$ - -# Fix some dragging issues with XWayland -windowrulev2 = nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0 - -# Flameshot configuration -windowrulev2 = noanim, class:^(flameshot)$ -windowrulev2 = float, class:^(flameshot)$ -windowrulev2 = move 0 0, class:^(flameshot)$ -windowrulev2 = pin, class:^(flameshot)$ -# Set this to your leftmost monitor id -windowrulev2 = monitor 0, class:^(flameshot)$ - -# Keybind with environment variable to fix copy issues -bind = SUPER_ALT, S, exec, XDG_CURRENT_DESKTOP=sway flameshot gui - -# MUSIC GAPLESS -windowrulev2 = float,class:^(com\.github\.neithern\.g4music)$ -windowrulev2 = size 356 573,class:^(com\.github\.neithern\.g4music)$ -windowrulev2 = move 2202 1025,class:^(com\.github\.neithern\.g4music)$ -#windowrulev2 = pin,class:^(com\.github\.neithern\.g4music)$ - -#windowrulev2 = tile, title:^Cisco Packet Tracer$ - -# NO SHARE SCREEN -windowrulev2 = noscreenshare, class:^(org\.telegram\.desktop)$ -windowrulev2 = noscreenshare, class:^(Signal)$ -windowrulev2 = noscreenshare, class:^(org\.keepassxc\.KeePassXC)$ -windowrulev2 = noscreenshare, class:^(com\.obsproject\.Studio)$ -#windowrulev2 = noscreenshare, class:^(org\.kde\.dolphin)$ -windowrulev2 = noscreenshare, class:^(vesktop)$ -windowrulev2 = noscreenshare, title:^(gsr ui)$ -windowrulev2 = noscreenshare, class:^(FreeTube)$ -windowrulev2 = noscreenshare, class:io.ente.auth -windowrulev2 = noscreenshare, class:^(librewolf)$ -#windowrulev2 = noscreenshare, class:^(librewolf)$, title:^(— LibreWolf)$ - -# WAYDROID -windowrulev2 = float, class:^(Waydroid)$ -windowrulev2 = center, class:^(Waydroid)$ -windowrulev2 = size 800 1280, class:^(Waydroid)$ - -# DRAW -workspace = special:gromit, gapsin:0, gapsout:0 -#exec-once = gromit-mpx -a -windowrulev2 = noblur, class:^(Gromit-mpx)$ -windowrulev2 = opacity 1 1, class:^(Gromit-mpx)$ -windowrulev2 = noshadow, class:^(Gromit-mpx)$ -#windowrulev2 = nofullscreenrequest, class:^(Gromit-mpx)$ -windowrulev2 = size 100% 100%, class:^(Gromit-mpx)$ - -# Always float and set size for Ente Auth -windowrulev2 = float, class:io.ente.auth -windowrulev2 = size 441 746, class:io.ente.auth - diff --git a/airootfs/etc/skel/.config/hypr/config/workflows.conf b/airootfs/etc/skel/.config/hypr/config/workflows.conf deleted file mode 100755 index bb2ae65..0000000 --- a/airootfs/etc/skel/.config/hypr/config/workflows.conf +++ /dev/null @@ -1,18 +0,0 @@ -#! █░█░█ █▀█ █▀█ █▄▀ █▀▀ █░░ █▀█ █░█░█ █▀ -#! ▀▄▀▄▀ █▄█ █▀▄ █░█ █▀░ █▄▄ █▄█ ▀▄▀▄▀ ▄█ - -# This file sets the current workflow for Hyprland -# HyDE Controlled content // DO NOT EDIT -# Edit or add workflows in the ./workflows/ directory -# and run the 'workflows.sh select' command to update this file - -# Workflows are a set of configurations that can be applied to Hyprland -# that suits the actual workflow you are doing. -# It can be gaming mode, work mode, or anything else you can think of. -# you can also exec a command within the workflow - -$WORKFLOW = default -$WORKFLOW_ICON =  -$WORKFLOW_DESCRIPTION = Default HyDE configuration // Disables workflow overrides -$WORKFLOWS_PATH = ./workflows/default.conf -source = $WORKFLOWS_PATH diff --git a/airootfs/etc/skel/.config/hypr/hyprland.conf b/airootfs/etc/skel/.config/hypr/hyprland.conf old mode 100755 new mode 100644 index ab361e1..f2fc970 --- a/airootfs/etc/skel/.config/hypr/hyprland.conf +++ b/airootfs/etc/skel/.config/hypr/hyprland.conf @@ -1,38 +1,201 @@ -# ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ -# ┃ CachyOS Hyprland Configuration ┃ -# ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ +# ┌──────────────────────────────────────────────────────────────────────────┐ +# │ SimulationOS - Hyprland configuration │ +# │ │ +# │ Deliberately small and flat so it can be debugged. Every command │ +# │ referenced here is provided by a package in packages.x86_64: │ +# │ kitty wofi thunar waybar mako hyprpaper hyprpolkitagent │ +# │ grim slurp wl-clipboard cliphist brightnessctl pavucontrol │ +# │ nm-connection-editor network-manager-applet blueman │ +# │ simos-screenshot simos-powermenu simos-clipboard (airootfs/usr/local) │ +# │ │ +# │ Put personal overrides in ~/.config/hypr/monitors.conf (sourced last). │ +# └──────────────────────────────────────────────────────────────────────────┘ $mainMod = SUPER +$terminal = kitty +$launcher = wofi --show drun +$fileManager = thunar -# ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ -# ┃ Source Files ┃ -# ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ -source = ~/.config/hypr/config/animations.conf -source = ~/.config/hypr/config/autostart.conf -source = ~/.config/hypr/config/decorations.conf -source = ~/.config/hypr/config/environment.conf -source = ~/.config/hypr/config/input.conf -source = ~/.config/hypr/config/keybinds.conf -source = ~/.config/hypr/config/monitor.conf -source = ~/.config/hypr/monitors.conf -source = ~/.config/hypr/config/variables.conf -source = ~/.config/hypr/config/windowrules.conf +# ──────────────────────────────────────────────────────────────── environment +env = XDG_CURRENT_DESKTOP,Hyprland +env = XDG_SESSION_TYPE,wayland +env = XDG_SESSION_DESKTOP,Hyprland +env = QT_QPA_PLATFORM,wayland;xcb +env = QT_WAYLAND_DISABLE_WINDOWDECORATION,1 +env = QT_AUTO_SCREEN_SCALE_FACTOR,1 +env = GDK_BACKEND,wayland,x11 +env = SDL_VIDEODRIVER,wayland +env = CLUTTER_BACKEND,wayland +env = MOZ_ENABLE_WAYLAND,1 +env = ELECTRON_OZONE_PLATFORM_HINT,auto +# Allows the session to come up on machines and VMs without a real GPU. +env = WLR_RENDERER_ALLOW_SOFTWARE,1 + +# ────────────────────────────────────────────────────────────────── autostart +# Order matters: the portal/dbus environment must be exported before apps that +# rely on it (file pickers, screensharing) are launched. +exec-once = dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP +exec-once = systemctl --user import-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP + +exec-once = hyprpaper +exec-once = waybar +exec-once = mako +exec-once = systemctl --user start hyprpolkitagent +exec-once = nm-applet --indicator +exec-once = blueman-applet +exec-once = wl-paste --watch cliphist store + +# ─────────────────────────────────────────────────────────────────── monitors +# Default: let Hyprland pick the preferred mode for every output. +monitor = , preferred, auto, 1 + +# ─────────────────────────────────────────────────────────────────────── input +input { + kb_layout = us + follow_mouse = 1 + sensitivity = 0 + touchpad { + natural_scroll = true + tap-to-click = true + disable_while_typing = true + } +} + +gestures { + workspace_swipe = true + workspace_swipe_fingers = 3 +} + +# ───────────────────────────────────────────────────────────────── appearance +general { + gaps_in = 4 + gaps_out = 8 + border_size = 2 + col.active_border = rgba(1793d1ee) rgba(33ccffee) 45deg + col.inactive_border = rgba(2a2a2aaa) + layout = dwindle + resize_on_border = true +} +decoration { + rounding = 8 + blur { + enabled = true + size = 3 + passes = 1 + } + shadow { + enabled = true + range = 12 + render_power = 3 + color = rgba(00000055) + } +} -#source = ~/.config/hypr/hyprlock.conf +animations { + enabled = true + bezier = easeOutQuint, 0.23, 1, 0.32, 1 + animation = windows, 1, 4, easeOutQuint, popin 90% + animation = fade, 1, 4, easeOutQuint + animation = workspaces, 1, 5, easeOutQuint, slide + animation = border, 1, 6, easeOutQuint +} -# Modifying these configs can be done by creating a user defined config in the home directory, e.g. -## ~/.config/hypr/config/user-config.conf -#source ~/.config/hypr/config/user-config.conf +dwindle { + pseudotile = true + preserve_split = true +} -#misc { -# no_focus_fallback = true -# disable_hyprland_urgency = true -#} +misc { + disable_hyprland_logo = true + disable_splash_rendering = true + force_default_wallpaper = 0 + font_family = Fira Sans +} +# Software cursors keep the pointer visible in VMs and on drivers with broken +# hardware cursor planes. SimulationOS is expected to be evaluated in a VM. +cursor { + no_hardware_cursors = true +} -#env = XDG_CURRENT_DESKTOP,KDE -#env = KDE_FULL_SESSION,true -#env = GTK_USE_PORTAL,1 +# ─────────────────────────────────────────────────────────────────── keybinds +bind = $mainMod, Return, exec, $terminal +bind = $mainMod, D, exec, $launcher +bind = $mainMod, E, exec, $fileManager +bind = $mainMod, Q, killactive, +bind = $mainMod SHIFT, E, exit, +bind = $mainMod, V, togglefloating, +bind = $mainMod, P, pseudo, +bind = $mainMod, J, togglesplit, +bind = $mainMod, F, fullscreen, 0 +bind = $mainMod, R, exec, hyprctl reload +bind = $mainMod, X, exec, simos-powermenu +bind = $mainMod, L, exec, hyprlock +bind = $mainMod, C, exec, simos-clipboard +bind = $mainMod SHIFT, N, exec, nm-connection-editor +# Screenshots +bind = , Print, exec, simos-screenshot full +bind = SHIFT, Print, exec, simos-screenshot area +bind = $mainMod, Print, exec, simos-screenshot window +# Focus +bind = $mainMod, left, movefocus, l +bind = $mainMod, right, movefocus, r +bind = $mainMod, up, movefocus, u +bind = $mainMod, down, movefocus, d + +# Move windows +bind = $mainMod SHIFT, left, movewindow, l +bind = $mainMod SHIFT, right, movewindow, r +bind = $mainMod SHIFT, up, movewindow, u +bind = $mainMod SHIFT, down, movewindow, d + +# Workspaces +bind = $mainMod, 1, workspace, 1 +bind = $mainMod, 2, workspace, 2 +bind = $mainMod, 3, workspace, 3 +bind = $mainMod, 4, workspace, 4 +bind = $mainMod, 5, workspace, 5 +bind = $mainMod, 6, workspace, 6 +bind = $mainMod, 7, workspace, 7 +bind = $mainMod, 8, workspace, 8 +bind = $mainMod, 9, workspace, 9 +bind = $mainMod, 0, workspace, 10 +bind = $mainMod SHIFT, 1, movetoworkspace, 1 +bind = $mainMod SHIFT, 2, movetoworkspace, 2 +bind = $mainMod SHIFT, 3, movetoworkspace, 3 +bind = $mainMod SHIFT, 4, movetoworkspace, 4 +bind = $mainMod SHIFT, 5, movetoworkspace, 5 +bind = $mainMod SHIFT, 6, movetoworkspace, 6 +bind = $mainMod SHIFT, 7, movetoworkspace, 7 +bind = $mainMod SHIFT, 8, movetoworkspace, 8 +bind = $mainMod SHIFT, 9, movetoworkspace, 9 +bind = $mainMod SHIFT, 0, movetoworkspace, 10 + +bind = $mainMod, mouse_down, workspace, e+1 +bind = $mainMod, mouse_up, workspace, e-1 +bindm = $mainMod, mouse:272, movewindow +bindm = $mainMod, mouse:273, resizewindow + +# Media / hardware keys +bindel = , XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+ +bindel = , XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%- +bindl = , XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle +bindl = , XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle +bindel = , XF86MonBrightnessUp, exec, brightnessctl set 5%+ +bindel = , XF86MonBrightnessDown, exec, brightnessctl set 5%- + +# ────────────────────────────────────────────────────────────────── windowrules +windowrulev2 = float, class:^(pavucontrol)$ +windowrulev2 = float, class:^(nm-connection-editor)$ +windowrulev2 = float, class:^(blueman-manager)$ +windowrulev2 = float, class:^(org.gnome.FileRoller)$ +windowrulev2 = float, title:^(Install SimulationOS)$ +windowrulev2 = size 1024 680, class:^(calamares)$ +windowrulev2 = center, class:^(calamares)$ +windowrulev2 = suppressevent maximize, class:.* + +# ───────────────────────────────────────────────────────── user overrides last +source = ~/.config/hypr/monitors.conf diff --git a/airootfs/etc/skel/.config/hypr/hyprlock.conf b/airootfs/etc/skel/.config/hypr/hyprlock.conf new file mode 100644 index 0000000..5aed749 --- /dev/null +++ b/airootfs/etc/skel/.config/hypr/hyprlock.conf @@ -0,0 +1,33 @@ +# SimulationOS - hyprlock +background { + monitor = + path = /usr/share/backgrounds/simulationos/simulationos-alpha.png + blur_passes = 2 + blur_size = 6 +} + +input-field { + monitor = + size = 320, 46 + outline_thickness = 2 + dots_center = true + outer_color = rgb(1793d1) + inner_color = rgb(14161a) + font_color = rgb(e6e6e6) + fail_color = rgb(c0392b) + placeholder_text = Password + position = 0, -40 + halign = center + valign = center +} + +label { + monitor = + text = SimulationOS + color = rgba(230, 230, 230, 1.0) + font_size = 30 + font_family = Fira Sans + position = 0, 60 + halign = center + valign = center +} diff --git a/airootfs/etc/skel/.config/hypr/hyprpaper.conf b/airootfs/etc/skel/.config/hypr/hyprpaper.conf old mode 100755 new mode 100644 index cbb27d7..691e130 --- a/airootfs/etc/skel/.config/hypr/hyprpaper.conf +++ b/airootfs/etc/skel/.config/hypr/hyprpaper.conf @@ -1,3 +1,6 @@ -preload = /mnt/m.2_ssd/Linux/Wallpapers/1354205.jpeg - -wallpaper = ,/mnt/m.2_ssd/Linux/Wallpapers/1354205.jpeg +# SimulationOS wallpaper. +# The image is shipped in airootfs/usr/share/backgrounds/simulationos/. +preload = /usr/share/backgrounds/simulationos/simulationos-alpha.png +wallpaper = , /usr/share/backgrounds/simulationos/simulationos-alpha.png +splash = false +ipc = on diff --git a/airootfs/etc/skel/.config/hypr/monitors.conf b/airootfs/etc/skel/.config/hypr/monitors.conf old mode 100755 new mode 100644 index fb5a07a..d8df80e --- a/airootfs/etc/skel/.config/hypr/monitors.conf +++ b/airootfs/etc/skel/.config/hypr/monitors.conf @@ -1,9 +1,11 @@ -# Generated by nwg-displays on 2025-04-09 at 10:17:38. Do not edit manually. - -#monitor=eDP-2,2560x1600.0,0x0,1.0,mirror,eDP-2 -monitor=HDMI-A-1,1920x1080@60.97,1920x0,1.0,mirror,eDP-2 -monitor=eDP-2,2560x1600@165,0x0,1.0 -#monitor=eDP-1,2560x1600@165,0x0,1.0 -monitor=eDP-1,2560x1600@60,0x0,1.0 - - +# SimulationOS - per-machine monitor and override file. +# +# This file is sourced at the END of hyprland.conf, so anything set here wins. +# It is intentionally empty by default: the generic +# monitor = , preferred, auto, 1 +# rule in hyprland.conf already configures every detected output. +# +# Examples: +# monitor = eDP-1, 1920x1080@60, 0x0, 1 +# monitor = HDMI-A-1, preferred, 1920x0, 1 +# monitor = , disable diff --git a/airootfs/etc/skel/.config/hypr/scripts/cava.js b/airootfs/etc/skel/.config/hypr/scripts/cava.js deleted file mode 100755 index 4950fd3..0000000 --- a/airootfs/etc/skel/.config/hypr/scripts/cava.js +++ /dev/null @@ -1,92 +0,0 @@ -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; - -const confPath = `/tmp/ags/cava.conf`; -async function readCavaAsync(barNumber, bitFormat, callback, onError) { - try { - const conf = -`[general] -framerate = 30 -bars = ${barNumber} -[output] -method = raw -bit_format = ${bitFormat}`; - - Utils.writeFileSync(conf, confPath); - - const cava = Gio.Subprocess.new( - [`cava`, `-p`, confPath], - Gio.SubprocessFlags.STDOUT_PIPE | - Gio.SubprocessFlags.STDERR_PIPE, - ); - - const pipe = cava.get_stdout_pipe(); - if (!pipe) { - onError(Error(`cava stdout pipe is null`)); - return null; - } - - const read8bit = (stream) => { - stream.read_bytes_async(barNumber, GLib.PRIORITY_LOW, null, (stream, res) => { - try { - let data = stream.read_bytes_finish(res).get_data(); - const output = new Float64Array(data).map(d => d / 255); - callback(output); - read8bit(stream); - } catch (e) { - onError(e); - } - }); - }; - const read16bit = (stream) => { - stream.read_bytes_async(barNumber * 2, GLib.PRIORITY_LOW, null, (stream, res) => { - try { - const data = stream.read_bytes_finish(res).get_data(); - const output = new Float64Array(new Uint16Array(data.buffer)).map(d => d / 65535); - callback(output); - read16bit(stream); - } catch (e) { - onError(e); - } - }); - }; - - if (bitFormat === '8bit') { - read8bit(pipe); - } else if (bitFormat === '16bit'){ - read16bit(pipe); - } - - } catch (e) { - logError(e); - return null; - } -} - -export class Cava extends Service { - static { - Service.register(this, {}, { - 'bar-value': ['float[]', 'r'], - }); - } - - #barValues = []; - get bar_value() { - return this.#barValues; - } - - constructor(barNumber, bitFormat) { - super(); - readCavaAsync( - barNumber, bitFormat, (barValues) => { - this.#barValues = barValues; - this.#onChange(); - } - ) - } - - #onChange() { - this.emit('changed'); - this.notify('bar-value'); - } -} diff --git a/airootfs/etc/skel/.config/hypr/scripts/cleanup.sh b/airootfs/etc/skel/.config/hypr/scripts/cleanup.sh deleted file mode 100755 index af4196d..0000000 --- a/airootfs/etc/skel/.config/hypr/scripts/cleanup.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -# ____ _ -# / ___| | ___ __ _ _ __ _ _ _ __ -# | | | |/ _ \/ _` | '_ \| | | | '_ \ -# | |___| | __/ (_| | | | | |_| | |_) | -# \____|_|\___|\__,_|_| |_|\__,_| .__/ -# |_| -# - -# Remove gamemode flag -if [ -f ~/.cache/gamemode ] ;then - rm ~/.cache/gamemode - echo ":: ~/.cache/gamemode removed" -fi \ No newline at end of file diff --git a/airootfs/etc/skel/.config/hypr/scripts/cpufreq.sh b/airootfs/etc/skel/.config/hypr/scripts/cpufreq.sh deleted file mode 100755 index c447d96..0000000 --- a/airootfs/etc/skel/.config/hypr/scripts/cpufreq.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash -MODE=$(auto-cpufreq --show | grep 'Current mode:' | awk '{print $3}') -case $1 in - powersave) - sudo auto-cpufreq --force powersave - ;; - performance) - sudo auto-cpufreq --force performance - ;; - reset) - sudo auto-cpufreq --force reset - ;; -esac -echo "$MODE" - diff --git a/airootfs/etc/skel/.config/hypr/scripts/gamemode.sh b/airootfs/etc/skel/.config/hypr/scripts/gamemode.sh deleted file mode 100755 index 09708fa..0000000 --- a/airootfs/etc/skel/.config/hypr/scripts/gamemode.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash -# ____ _ -# / ___| __ _ _ __ ___ ___ _ __ ___ ___ __| | ___ -# | | _ / _` | '_ ` _ \ / _ \ '_ ` _ \ / _ \ / _` |/ _ \ -# | |_| | (_| | | | | | | __/ | | | | | (_) | (_| | __/ -# \____|\__,_|_| |_| |_|\___|_| |_| |_|\___/ \__,_|\___| -# -# - -if [ -f ~/.cache/gamemode ] ;then - hyprctl reload - rm ~/.cache/gamemode - notify-send "Gamemode deactivated" "Animations and blur enabled" -else - hyprctl --batch "\ - keyword animations:enabled 0;\ - keyword decoration:drop_shadow 0;\ - keyword decoration:blur:enabled 0;\ - keyword general:gaps_in 0;\ - keyword general:gaps_out 0;\ - keyword general:border_size 1;\ - keyword decoration:rounding 0" - touch ~/.cache/gamemode - notify-send "Gamemode activated" "Animations and blur disabled" -fi diff --git a/airootfs/etc/skel/.config/hypr/scripts/generate_wallpapers.sh b/airootfs/etc/skel/.config/hypr/scripts/generate_wallpapers.sh deleted file mode 100755 index 056bd11..0000000 --- a/airootfs/etc/skel/.config/hypr/scripts/generate_wallpapers.sh +++ /dev/null @@ -1,97 +0,0 @@ -#!/bin/bash - -print_help() { - echo "Usage: wallpaper-changer.sh [-p PATH] [-i INTERVAL] [-h|--help]" - echo - echo "Options:" - echo -e " -i, --interval INTERVAL\tTime interval (in seconds) between wallpaper changes" - echo -e " -p, --path PATH\tpath to load wallpapers from.Default value is ~/Pictures/Wallpapers. Does not recursively load wallpapers" - echo -e " -m, --monitor MONITOR_NAME \t monitor for which the wallpapers must be applied. Use hyprctl monitors to see the list of monitors." - echo " -h, --help Print this help message and exit" -} - -preload_wallpapers() { - wallpaper_dir=$1 - wallpapers=$(find "$wallpaper_dir" -type f) - wallpapers_string="" - OLDIFS=$IFS - IFS=$'\n' - for wallpaper in $wallpapers; do - wallpapers_string+="preload = $wallpaper\n" - done - echo -en "$wallpapers_string" >>/tmp/wallpapers.tmp - touch ~/.config/hypr/hyprpaper.conf.tmp - cat /tmp/wallpapers.tmp ~/.config/hypr/hyprpaper.conf >~/.config/hypr/hyprpaper.conf.tmp && mv ~/.config/hypr/hyprpaper.conf.tmp ~/.config/hypr/hyprpaper.conf - rm /tmp/wallpapers.tmp - IFS=$OLDIFS - -} - -# set the path to the wallpaper directory -wallpaper_dir="/mnt/m.2_ssd/Linux/Wallpapers" - -# parse the command line arguments -interval=300 -while getopts ":hi:p:m:-:" opt; do - case $opt in - -) - case "${OPTARG}" in - interval) - interval=$OPTIND - OPTIND=$((OPTIND + 1)) - ;; - help) - print_help - exit 0 - ;; - path) - wallpaper_dir=$OPTIND - OPTIND=$((OPTIND + 1)) - ;; - esac - ;; - h) - print_help - exit 0 - ;; - i) - interval=$OPTARG - ;; - p) - wallpaper_dir=$OPTARG - ;; - m) - monitors=$OPTARG - ;; - - \?) - echo "Invalid option: -$OPTARG" >&2 - exit 1 - ;; - :) - echo "Option -$OPTARG requires an argument." >&2 - exit 1 - ;; - esac -done -if [ -z "$monitors" ]; then - echo "Error: -m/--monitors option is required" >&2 - exit 1 -fi -preload_wallpapers "$wallpaper_dir" -# get a list of all the wallpapers in the wallpaper directory -readarray -d '' wallpapers < <(find "$wallpaper_dir" -type f -print0) -killall hyprpaper -hyprpaper >/dev/null 2>&1 & -disown - -idx=0 -n=${#wallpapers[@]} -while true; do - # wait for the specified interval - sleep "$interval" - current_wallpaper=${wallpapers[$idx]} - wallpaper_cmd="hyprctl hyprpaper wallpaper $monitors,\"$current_wallpaper\"" - eval "$wallpaper_cmd" - idx=$(((idx + 1) % n)) -done diff --git a/airootfs/etc/skel/.config/hypr/scripts/init-wallpaper-engine.sh b/airootfs/etc/skel/.config/hypr/scripts/init-wallpaper-engine.sh deleted file mode 100755 index 6751156..0000000 --- a/airootfs/etc/skel/.config/hypr/scripts/init-wallpaper-engine.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash -# __ ______ _____ _ -# \ \ / / _ \ | ____|_ __ __ _(_)_ __ ___ -# \ \ /\ / /| |_) | | _| | '_ \ / _` | | '_ \ / _ \ -# \ V V / | __/ | |___| | | | (_| | | | | | __/ -# \_/\_/ |_| |_____|_| |_|\__, |_|_| |_|\___| -# |___/ -# - -wallpaper_engine=$(cat $HOME/.config/ml4w/settings/wallpaper-engine.sh) -if [ "$wallpaper_engine" == "swww" ] ;then - # swww - echo ":: Using swww" - swww init - swww-daemon --format xrgb - sleep 0.5 - ~/.config/hypr/scripts/wallpaper.sh init -elif [ "$wallpaper_engine" == "hyprpaper" ] ;then - # hyprpaper - echo ":: Using hyprpaper" - sleep 0.5 - ~/.config/hypr/scripts/wallpaper.sh init -else - echo ":: Wallpaper Engine disabled" - ~/.config/hypr/scripts/wallpaper.sh init -fi - diff --git a/airootfs/etc/skel/.config/hypr/scripts/internal-mic.sh b/airootfs/etc/skel/.config/hypr/scripts/internal-mic.sh deleted file mode 100755 index a932ec8..0000000 --- a/airootfs/etc/skel/.config/hypr/scripts/internal-mic.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/bash - -# Define sinks (output devices) -USB_SINK="alsa_output.usb-GeneralPlus_USB_Audio_Device-00.analog-stereo" -SPEAKER_SINK="alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__Speaker__sink" - -# Define laptop mic (input device) -LAPTOP_MIC="alsa_input.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__Mic1__source" - -# Function to move all app streams to the current default sink -move_streams_to_default_sink() { - DEFAULT_SINK=$(pactl info | grep "Default Sink" | awk '{print $3}') - pactl list short sink-inputs | while read -r id _; do - pactl move-sink-input "$id" "$DEFAULT_SINK" - done -} - -# Function to set mic volume and unmute -set_laptop_mic() { - pactl set-default-source "$LAPTOP_MIC" - pactl set-source-volume "$LAPTOP_MIC" 60% - pactl set-source-mute "$LAPTOP_MIC" 0 -} - -# Get current default sink -CURRENT_SINK=$(pactl info | grep 'Default Sink' | awk '{print $3}') - -# Toggle output sink and apply laptop mic -# if [[ "$CURRENT_SINK" == "$USB_SINK" ]]; then -# pactl set-default-sink "$SPEAKER_SINK" -# pactl set-sink-mute "$SPEAKER_SINK" 0 -# pactl set-sink-volume "$SPEAKER_SINK" 100% -# echo "Switched to Speaker output" -# else -# pactl set-default-sink "$USB_SINK" -# pactl set-sink-mute "$USB_SINK" 0 -# echo "Switched to USB output" -# fi - -# Apply laptop mic settings -set_laptop_mic -echo "Laptop Microphone set as input with 70% volume" - -# Move all streams to current default sink -move_streams_to_default_sink -echo "All app streams moved to default sink" diff --git a/airootfs/etc/skel/.config/hypr/scripts/kill-window.sh b/airootfs/etc/skel/.config/hypr/scripts/kill-window.sh deleted file mode 100755 index d829142..0000000 --- a/airootfs/etc/skel/.config/hypr/scripts/kill-window.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -notify-send -u critical -t 500 "Kill" "Click any window kill it" -hyprctl kill - diff --git a/airootfs/etc/skel/.config/hypr/scripts/light.sh b/airootfs/etc/skel/.config/hypr/scripts/light.sh deleted file mode 100755 index 7287d03..0000000 --- a/airootfs/etc/skel/.config/hypr/scripts/light.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -CONTENT=$(curl -s http://ip-api.com/json/) -longitude=$(echo $CONTENT | jq .lon) -latitude=$(echo $CONTENT | jq .lat) -wlsunset -l $latitude -L $longitude - diff --git a/airootfs/etc/skel/.config/hypr/scripts/loadconfig.sh b/airootfs/etc/skel/.config/hypr/scripts/loadconfig.sh deleted file mode 100755 index a51ce6d..0000000 --- a/airootfs/etc/skel/.config/hypr/scripts/loadconfig.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -hyprctl reload \ No newline at end of file diff --git a/airootfs/etc/skel/.config/hypr/scripts/manage_wallpaper.sh b/airootfs/etc/skel/.config/hypr/scripts/manage_wallpaper.sh deleted file mode 100755 index bb2e167..0000000 --- a/airootfs/etc/skel/.config/hypr/scripts/manage_wallpaper.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -WALLPAPER_DIR="/mnt/m.2_ssd/Linux/Wallpapers" -IMAGE=$(find "$WALLPAPER_DIR" -type f \( -iname "*.jpg" -o -iname "*.png" -o -iname "*.jpeg" \) | shuf -n 1) - -# Supported transitions -TRANSITIONS=("wipe" "grow" "outer" "center" "fade" "simple" "left" "right" "top" "bottom" "wave") -TRANSITION=${TRANSITIONS[$RANDOM % ${#TRANSITIONS[@]}]} - -# Random normalized position (0.0–1.0) -POS_X=$(awk -v seed=$RANDOM 'BEGIN { srand(seed); printf("%.2f", rand()) }') -POS_Y=$(awk -v seed=$RANDOM 'BEGIN { srand(seed); printf("%.2f", rand()) }') - -# Start swww-daemon if not already running -if ! pgrep -x swww-daemon >/dev/null; then - swww-daemon & - sleep 0.5 -fi - -# Set wallpaper with random transition and position -swww img "$IMAGE" --transition-type "$TRANSITION" --transition-pos "$POS_X,$POS_Y" --transition-duration 3 --transition-fps 60 - - diff --git a/airootfs/etc/skel/.config/hypr/scripts/mic-default-volume.sh b/airootfs/etc/skel/.config/hypr/scripts/mic-default-volume.sh deleted file mode 100755 index 40bcbd8..0000000 --- a/airootfs/etc/skel/.config/hypr/scripts/mic-default-volume.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -sleep 5 - -wpctl set-volume @DEFAULT_AUDIO_SOURCE@ 0.4 - - -#!/bin/bash - -# Set USB mic as default input -pactl set-default-source alsa_input.usb-GeneralPlus_USB_Audio_Device-00.mono-fallback -#pactl set-source-volume alsa_input.usb-GeneralPlus_USB_Audio_Device-00.mono-fallback 100% -pactl set-source-mute alsa_input.usb-GeneralPlus_USB_Audio_Device-00.mono-fallback 0 - -# Mute all other mics -pactl set-source-mute alsa_input.usb-Sony_Interactive_Entertainment_DualSense_Wireless_Controller-00.analog-stereo 1 -pactl set-source-mute alsa_input.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__Mic1__source 1 -pactl set-source-mute alsa_input.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__Mic2__source 1 - diff --git a/airootfs/etc/skel/.config/hypr/scripts/power.sh b/airootfs/etc/skel/.config/hypr/scripts/power.sh deleted file mode 100755 index 8d7394e..0000000 --- a/airootfs/etc/skel/.config/hypr/scripts/power.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash -# ____ -# | _ \ _____ _____ _ __ -# | |_) / _ \ \ /\ / / _ \ '__| -# | __/ (_) \ V V / __/ | -# |_| \___/ \_/\_/ \___|_| -# - -if [[ "$1" == "exit" ]]; then - echo ":: Exit" - if [[ -f "$FILE" ]]; then - rm $FILE - fi - sleep 0.5 - killall -9 Hyprland - sleep 2 -fi - -if [[ "$1" == "lock" ]]; then - echo ":: Lock" - sleep 0.5 - hyprlock -fi - -if [[ "$1" == "reboot" ]]; then - echo ":: Reboot" - if [[ -f "$FILE" ]]; then - rm $FILE - fi - sleep 0.5 - systemctl reboot -fi - -if [[ "$1" == "shutdown" ]]; then - echo ":: Shutdown" - if [[ -f "$FILE" ]]; then - rm $FILE - fi - sleep 0.5 - systemctl poweroff -fi - -if [[ "$1" == "suspend" ]]; then - echo ":: Suspend" - sleep 0.5 - systemctl suspend -fi - -if [[ "$1" == "hibernate" ]]; then - echo ":: Hibernate" - sleep 1 - systemctl hibernate -fi - diff --git a/airootfs/etc/skel/.config/hypr/scripts/screenshot b/airootfs/etc/skel/.config/hypr/scripts/screenshot deleted file mode 100755 index ecc11b9..0000000 --- a/airootfs/etc/skel/.config/hypr/scripts/screenshot +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/bash -grim -g "$(slurp)" - | wl-copy -t image/png -notify-send "Screenshot copied to clipboard" diff --git a/airootfs/etc/skel/.config/hypr/scripts/screenshot.sh b/airootfs/etc/skel/.config/hypr/scripts/screenshot.sh deleted file mode 100755 index d08557a..0000000 --- a/airootfs/etc/skel/.config/hypr/scripts/screenshot.sh +++ /dev/null @@ -1,224 +0,0 @@ -#!/bin/bash -# ____ _ _ -# / ___| ___ _ __ ___ ___ _ __ ___| |__ ___ | |_ -# \___ \ / __| '__/ _ \/ _ \ '_ \/ __| '_ \ / _ \| __| -# ___) | (__| | | __/ __/ | | \__ \ | | | (_) | |_ -# |____/ \___|_| \___|\___|_| |_|___/_| |_|\___/ \__| -# -# Based on https://github.com/hyprwm/contrib/blob/main/grimblast/screenshot.sh -# ----------------------------------------------------- - -# Screenshots will be stored in $HOME by default. -# The screenshot will be moved into the screenshot directory - -# Add this to ~/.config/user-dirs.dirs to save screenshots in a custom folder: -# XDG_SCREENSHOTS_DIR="$HOME/Screenshots" - -prompt='Screenshot' -mesg="DIR: ~/Screenshots" - -# Screenshot Filename -source ~/.config/ml4w/settings/screenshot-filename.sh - -# Screenshot Folder -source ~/.config/ml4w/settings/screenshot-folder.sh - -# Screenshot Editor -export GRIMBLAST_EDITOR="$(cat ~/.config/ml4w/settings/screenshot-editor.sh)" - -# Example for keybindings -# bind = SUPER, p, exec, grimblast save active -# bind = SUPER SHIFT, p, exec, grimblast save area -# bind = SUPER ALT, p, exec, grimblast save output -# bind = SUPER CTRL, p, exec, grimblast save screen - -# Options -option_1="Immediate" -option_2="Delayed" - -option_capture_1="Capture Everything" -option_capture_2="Capture Active Display" -option_capture_3="Capture Selection" - -option_time_1="5s" -option_time_2="10s" -option_time_3="20s" -option_time_4="30s" -option_time_5="60s" -#option_time_4="Custom (in seconds)" # Roadmap or someone contribute :) - -list_col='1' -list_row='2' - -copy='Copy' -save='Save' -copy_save='Copy & Save' -edit='Edit' - -# Rofi CMD -rofi_cmd() { - rofi -dmenu -replace -config ~/.config/rofi/config-screenshot.rasi -i -no-show-icons -l 2 -width 30 -p "Take screenshot" -} - -# Pass variables to rofi dmenu -run_rofi() { - echo -e "$option_1\n$option_2" | rofi_cmd -} - -#### -# Choose Timer -# CMD -timer_cmd() { - rofi -dmenu -replace -config ~/.config/rofi/config-screenshot.rasi -i -no-show-icons -l 5 -width 30 -p "Choose timer" -} - -# Ask for confirmation -timer_exit() { - echo -e "$option_time_1\n$option_time_2\n$option_time_3\n$option_time_4\n$option_time_5" | timer_cmd -} - -# Confirm and execute -timer_run() { - selected_timer="$(timer_exit)" - if [[ "$selected_timer" == "$option_time_1" ]]; then - countdown=5 - ${1} - elif [[ "$selected_timer" == "$option_time_2" ]]; then - countdown=10 - ${1} - elif [[ "$selected_timer" == "$option_time_3" ]]; then - countdown=20 - ${1} - elif [[ "$selected_timer" == "$option_time_4" ]]; then - countdown=30 - ${1} - elif [[ "$selected_timer" == "$option_time_5" ]]; then - countdown=60 - ${1} - else - exit - fi -} -### - -#### -# Chose Screenshot Type -# CMD -type_screenshot_cmd() { - rofi -dmenu -replace -config ~/.config/rofi/config-screenshot.rasi -i -no-show-icons -l 3 -width 30 -p "Type of screenshot" -} - -# Ask for confirmation -type_screenshot_exit() { - echo -e "$option_capture_1\n$option_capture_2\n$option_capture_3" | type_screenshot_cmd -} - -# Confirm and execute -type_screenshot_run() { - selected_type_screenshot="$(type_screenshot_exit)" - if [[ "$selected_type_screenshot" == "$option_capture_1" ]]; then - option_type_screenshot=screen - ${1} - elif [[ "$selected_type_screenshot" == "$option_capture_2" ]]; then - option_type_screenshot=output - ${1} - elif [[ "$selected_type_screenshot" == "$option_capture_3" ]]; then - option_type_screenshot=area - ${1} - else - exit - fi -} -### - -#### -# Choose to save or copy photo -# CMD -copy_save_editor_cmd() { - rofi -dmenu -replace -config ~/.config/rofi/config-screenshot.rasi -i -no-show-icons -l 4 -width 30 -p "How to save" -} - -# Ask for confirmation -copy_save_editor_exit() { - echo -e "$copy\n$save\n$copy_save\n$edit" | copy_save_editor_cmd -} - -# Confirm and execute -copy_save_editor_run() { - selected_chosen="$(copy_save_editor_exit)" - if [[ "$selected_chosen" == "$copy" ]]; then - option_chosen=copy - ${1} - elif [[ "$selected_chosen" == "$save" ]]; then - option_chosen=save - ${1} - elif [[ "$selected_chosen" == "$copy_save" ]]; then - option_chosen=copysave - ${1} - elif [[ "$selected_chosen" == "$edit" ]]; then - option_chosen=edit - ${1} - else - exit - fi -} -### - -timer() { - if [[ $countdown -gt 10 ]]; then - notify-send -t 1000 "Taking screenshot in ${countdown} seconds" - countdown_less_10=$((countdown - 10)) - sleep $countdown_less_10 - countdown=10 - fi - while [[ $countdown -ne 0 ]]; do - notify-send -t 1000 "Taking screenshot in ${countdown} seconds" - countdown=$((countdown - 1)) - sleep 1 - done -} - -# take shots -takescreenshot() { - sleep 1 - grimblast --notify "$option_chosen" "$option_type_screenshot" $NAME - if [ -f $HOME/$NAME ] ;then - if [ -d $screenshot_folder ] ;then - mv $HOME/$NAME $screenshot_folder/ - fi - fi -} - -takescreenshot_timer() { - sleep 1 - timer - grimblast --notify "$option_chosen" "$option_type_screenshot" $NAME - if [ -f $HOME/$NAME ] ;then - if [ -d $screenshot_folder ] ;then - mv $HOME/$NAME $screenshot_folder/ - fi - fi -} - -# Execute Command -run_cmd() { - if [[ "$1" == '--opt1' ]]; then - type_screenshot_run - copy_save_editor_run "takescreenshot" - elif [[ "$1" == '--opt2' ]]; then - timer_run - type_screenshot_run - copy_save_editor_run "takescreenshot_timer" - fi -} - -# Actions -chosen="$(run_rofi)" -case ${chosen} in -$option_1) - run_cmd --opt1 - ;; -$option_2) - run_cmd --opt2 - ;; -esac diff --git a/airootfs/etc/skel/.config/hypr/scripts/screenshot_area b/airootfs/etc/skel/.config/hypr/scripts/screenshot_area deleted file mode 100755 index 52218e2..0000000 --- a/airootfs/etc/skel/.config/hypr/scripts/screenshot_area +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/bash -grimblast copy area || exit -notify-send "Screenshot copied to clipboard" diff --git a/airootfs/etc/skel/.config/hypr/scripts/screenshot_full b/airootfs/etc/skel/.config/hypr/scripts/screenshot_full deleted file mode 100755 index 0608891..0000000 --- a/airootfs/etc/skel/.config/hypr/scripts/screenshot_full +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/bash -grimblast copy output || exit -notify-send "Screenshot copied to clipboard" diff --git a/airootfs/etc/skel/.config/hypr/scripts/switch_audio.sh b/airootfs/etc/skel/.config/hypr/scripts/switch_audio.sh deleted file mode 100755 index 74bc8a1..0000000 --- a/airootfs/etc/skel/.config/hypr/scripts/switch_audio.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash - -# Define sinks (output devices) -USB_SINK="alsa_output.usb-GeneralPlus_USB_Audio_Device-00.analog-stereo" -SPEAKER_SINK="alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__Speaker__sink" - -# Define USB mic (input device) -USB_MIC="alsa_input.usb-GeneralPlus_USB_Audio_Device-00.mono-fallback" - -# Function to move all app streams to the current default sink -move_streams_to_default_sink() { - DEFAULT_SINK=$(pactl info | grep "Default Sink" | awk '{print $3}') - pactl list short sink-inputs | while read -r id _; do - pactl move-sink-input "$id" "$DEFAULT_SINK" - done -} - -# Function to set mic volume and unmute -set_usb_mic() { - pactl set-default-source "$USB_MIC" - pactl set-source-volume "$USB_MIC" 70% - pactl set-source-mute "$USB_MIC" 0 -} - -# Get current default sink -CURRENT_SINK=$(pactl info | grep 'Default Sink' | awk '{print $3}') - -# Toggle output sink and apply USB mic -if [[ "$CURRENT_SINK" == "$USB_SINK" ]]; then - pactl set-default-sink "$SPEAKER_SINK" - pactl set-sink-mute "$SPEAKER_SINK" 0 - pactl set-sink-volume "$SPEAKER_SINK" 100% - echo "Switched to Speaker output" -else - pactl set-default-sink "$USB_SINK" - pactl set-sink-mute "$USB_SINK" 0 - echo "Switched to USB output" -fi - -# Apply USB mic settings -set_usb_mic -echo "USB Microphone set as input with 100% volume" - -# Move all streams to current default sink -move_streams_to_default_sink -echo "All app streams moved to default sink" - diff --git a/airootfs/etc/skel/.config/hypr/scripts/toggle-touchpad.sh b/airootfs/etc/skel/.config/hypr/scripts/toggle-touchpad.sh deleted file mode 100755 index 2b5dafb..0000000 --- a/airootfs/etc/skel/.config/hypr/scripts/toggle-touchpad.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh - -# Fast touchpad toggle for Hyprland - streamlined version - -# Find the touchpad device event number -TOUCHPAD_EVENT=$(grep -A 5 -B 5 "SYNA7DB5:00 06CB:CEAF Touchpad" /proc/bus/input/devices | grep -o 'event[0-9]*' | head -n1) - -[ -z "$TOUCHPAD_EVENT" ] && { notify-send -t 1000 "Error: Touchpad not found"; exit 1; } - -# Path to the device inhibit file -INHIBIT_FILE="/sys/class/input/$TOUCHPAD_EVENT/device/inhibited" - -# Check current state and toggle (0=enabled, 1=disabled) -CURRENT_STATE=$(cat "$INHIBIT_FILE" 2>/dev/null || echo "0") - -if [ "$CURRENT_STATE" = "0" ]; then - if echo 1 | tee "$INHIBIT_FILE" >/dev/null 2>&1; then - notify-send -t 1000 "Touchpad Disabled" - else - notify-send -t 1000 "Failed to disable" - fi -else - if echo 0 | tee "$INHIBIT_FILE" >/dev/null 2>&1; then - notify-send -t 1000 "Touchpad Enabled" - else - notify-send -t 1000 "Failed to enable" - fi -fi diff --git a/airootfs/etc/skel/.config/hypr/scripts/toggle_display.sh b/airootfs/etc/skel/.config/hypr/scripts/toggle_display.sh deleted file mode 100755 index e40cb77..0000000 --- a/airootfs/etc/skel/.config/hypr/scripts/toggle_display.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -STATUS=$(hyprctl monitors -j | jq -r '.[] | select(.name=="eDP-2") | .dpmsStatus') - -if [[ "$STATUS" == "true" ]]; then - hyprctl dispatch dpms off eDP-2 -else - hyprctl dispatch dpms on eDP-2 -fi - diff --git a/airootfs/etc/skel/.config/hypr/scripts/toggle_mic.sh b/airootfs/etc/skel/.config/hypr/scripts/toggle_mic.sh deleted file mode 100755 index 9d1a1ad..0000000 --- a/airootfs/etc/skel/.config/hypr/scripts/toggle_mic.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash -# Get only microphone sources (exclude monitors and virtual sources) -SOURCES=$(pamixer --list-sources | grep -v "monitor" | grep -v "virtual" | awk -F: '{print $1}') - -# Toggle mute for microphone sources only -for SRC in $SOURCES; do - pamixer --source "$SRC" --toggle-mute -done - -# Check and report the state of the default source -MIC_STATE=$(pamixer --default-source --get-mute) -if [ "$MIC_STATE" = "true" ]; then - notify-send -u low -i microphone-sensitivity-high -t 1000 "Microphone" "Muted" -else - notify-send -u low -i microphone-sensitivity-high -t 1000 "Microphone" "Unmuted" -fi diff --git a/airootfs/etc/skel/.config/hypr/scripts/wallpaper-cache.sh b/airootfs/etc/skel/.config/hypr/scripts/wallpaper-cache.sh deleted file mode 100755 index 899a06a..0000000 --- a/airootfs/etc/skel/.config/hypr/scripts/wallpaper-cache.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -generated_versions="$HOME/.config/ml4w/cache/wallpaper-generated" -rm $generated_versions/* -echo ":: Wallpaper cache cleared" -notify-send "Wallpaper cache cleared" \ No newline at end of file diff --git a/airootfs/etc/skel/.config/hypr/scripts/wallpaper-restore.sh b/airootfs/etc/skel/.config/hypr/scripts/wallpaper-restore.sh deleted file mode 100755 index 9c6cd6e..0000000 --- a/airootfs/etc/skel/.config/hypr/scripts/wallpaper-restore.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/bash -# _ _ -# __ ____ _| | |_ __ __ _ _ __ ___ _ __ -# \ \ /\ / / _` | | | '_ \ / _` | '_ \ / _ \ '__| -# \ V V / (_| | | | |_) | (_| | |_) | __/ | -# \_/\_/ \__,_|_|_| .__/ \__,_| .__/ \___|_| -# |_| |_| -# -# ----------------------------------------------------- -# Restore last wallpaper -# ----------------------------------------------------- - -# ----------------------------------------------------- -# Set defaults -# ----------------------------------------------------- - -defaultwallpaper="$HOME/wallpaper/default.jpg" -cachefile="$HOME/.config/ml4w/cache/current_wallpaper" - -# ----------------------------------------------------- -# Get current wallpaper -# ----------------------------------------------------- - -if [ -f $cachefile ] ;then - if [ -f $(cat $cachefile) ]; then - echo ":: Wallpaper $(cat $cachefile) exists" - wallpaper=$(cat $cachefile) - else - echo ":: Wallpaper $(cat $cachefile) not exists." - wallpaper=$defaultwallpaper - fi -else - echo ":: $cachefile not exists." - wallpaper=$defaultwallpaper -fi - -# ----------------------------------------------------- -# Set wallpaper -# ----------------------------------------------------- - -echo ":: Setting wallpaper with source image $wallpaper" -waypaper --wallpaper $wallpaper \ No newline at end of file diff --git a/airootfs/etc/skel/.config/hypr/scripts/wallpaper.sh b/airootfs/etc/skel/.config/hypr/scripts/wallpaper.sh deleted file mode 100755 index dfb453f..0000000 --- a/airootfs/etc/skel/.config/hypr/scripts/wallpaper.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash -# _ _ -# __ ____ _| | |_ __ __ _ _ __ ___ _ __ -# \ \ /\ / / _` | | | '_ \ / _` | '_ \ / _ \ '__| -# \ V V / (_| | | | |_) | (_| | |_) | __/ | -# \_/\_/ \__,_|_|_| .__/ \__,_| .__/ \___|_| -# |_| |_| -# -# ----------------------------------------------------- -# Execute pywal -# ----------------------------------------------------- - -echo ":: Execute pywal with $used_wallpaper" -wal -i ~/wallpapers/cachyos-wallpapers/ $used_wallpaper -q --cols16 - -# ----------------------------------------------------- -# Reload Waybar -# ----------------------------------------------------- - -$HOME/.config/waybar/launch.sh - -# ----------------------------------------------------- -# Pywalfox -# ----------------------------------------------------- - -if type pywalfox >/dev/null 2>&1; then - pywalfox update -fi diff --git a/airootfs/etc/skel/.config/hypr/scripts/wofi-clipbaord.sh b/airootfs/etc/skel/.config/hypr/scripts/wofi-clipbaord.sh deleted file mode 100755 index 0a6fed5..0000000 --- a/airootfs/etc/skel/.config/hypr/scripts/wofi-clipbaord.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -entries=$(cliphist list) - -selection=$(echo "$entries" | wofi --dmenu --prompt "Clipboard") - -if [[ -z "$selection" ]]; then - exit 0 -fi - -# Use cliphist to decode and copy -echo "$selection" | cliphist decode | wl-copy - diff --git a/airootfs/etc/skel/.config/hypr/scripts/xdg.sh b/airootfs/etc/skel/.config/hypr/scripts/xdg.sh deleted file mode 100755 index 6177b64..0000000 --- a/airootfs/etc/skel/.config/hypr/scripts/xdg.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash -# __ ______ ____ -# \ \/ / _ \ / ___| -# \ /| | | | | _ -# / \| |_| | |_| | -# /_/\_\____/ \____| -# - -sleep 1 - -# kill all possible running xdg-desktop-portals -killall -e xdg-desktop-portal-hyprland -killall -e xdg-desktop-portal-gnome -killall -e xdg-desktop-portal-kde -killall -e xdg-desktop-portal-lxqt -killall -e xdg-desktop-portal-wlr -killall -e xdg-desktop-portal-gtk -killall -e xdg-desktop-portal -sleep 1 - -# start xdg-desktop-portal-hyprland -/usr/lib/xdg-desktop-portal-hyprland & -sleep 2 - -# start xdg-desktop-portal-gtk -if [ -f /usr/lib/xdg-desktop-portal-gtk ] ;then - /usr/lib/xdg-desktop-portal-gtk & - sleep 1 -fi - -# start xdg-desktop-portal -/usr/lib/xdg-desktop-portal & -sleep 1 \ No newline at end of file diff --git a/airootfs/etc/skel/.config/hypr/wallpapers.conf b/airootfs/etc/skel/.config/hypr/wallpapers.conf deleted file mode 100755 index 67d8576..0000000 --- a/airootfs/etc/skel/.config/hypr/wallpapers.conf +++ /dev/null @@ -1,100 +0,0 @@ -# Autogenerated by generate_wallpapers.sh -preload = /mnt/m.2_ssd/Linux/Wallpapers/1374345.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/1606897678677.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/1645962188236.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/185172182e113-screenshotUrl.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/185174785b28-screenshotUrl.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/185b3478b6571-screenshotUrl.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/1860b6f425825-screenshotUrl.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/1860b70503b7-screenshotUrl.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/1860c68af7a47-screenshotUrl.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/18a6c3dbcf085-screenshotUrl.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/18b22b9700271-screenshotUrl.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/20240607_184614.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/4.49a9d9bc4812520ba537c6c4f83de8b8.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/508286.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/5f3kzz9ga1y31.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/641193.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/72270.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/850.Mixed Wallpapers (207).jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/976234.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/9k48ji18et011.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/ae4xtKY.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/b4gl7p2j83u61.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/Bloodborne™_20220111055336.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/bored-at-home-try-some-windows-vhd256fzppknmaz8.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/cat-meme-background-f9i99husnvjkk492.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/CN62QXJ.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/ComputerDesktopWallpapersCollection1691__088.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/humor-wallpaper-preview.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/ii8669b9lz001.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/impoppy-20220404-0001.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/jx0cehys3yr31.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/kbrpdbfy1rmy.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/kxblq0jrdkyz.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/l7hn0bm9nom71.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/Linx.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/n1ci0trfgrey.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/penguin.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/Remini20220222180405870.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/The-Witcher-The-Witcher-3-Wild-Hunt-video-games-RPG-Video-Game-Art-1658261-wallhere.com.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/undefined - Imgur.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/wallpaperflare.com_wallpaper (1).jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/wallpaperflare.com_wallpaper (2).jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/wallpaperflare.com_wallpaper (3).jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/wallpaperflare.com_wallpaper (4).jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/wallpaperflare.com_wallpaper.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/wallpaperflare.com_wsallpaper.jpg -preload = /mnt/m.2_ssd/Linux/Wallpapers/1346531.jpeg -preload = /mnt/m.2_ssd/Linux/Wallpapers/1354205.jpeg -preload = /mnt/m.2_ssd/Linux/Wallpapers/4ccEiRx.jpeg -preload = /mnt/m.2_ssd/Linux/Wallpapers/9heDmcF.jpeg -preload = /mnt/m.2_ssd/Linux/Wallpapers/a16v87sw8rge1.jpeg -preload = /mnt/m.2_ssd/Linux/Wallpapers/GLnEJQm.jpeg -preload = /mnt/m.2_ssd/Linux/Wallpapers/hMWc6jB.jpeg -preload = /mnt/m.2_ssd/Linux/Wallpapers/Life+Goes+On.jpeg -preload = /mnt/m.2_ssd/Linux/Wallpapers/Melon+Dog.jpeg -preload = /mnt/m.2_ssd/Linux/Wallpapers/rXsN7UY.jpeg -preload = /mnt/m.2_ssd/Linux/Wallpapers/SU15wjN.jpeg -preload = /mnt/m.2_ssd/Linux/Wallpapers/1330715.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/1332803.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/1338180.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/1341419.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/1351005.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/2024-08-31_14-24.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/727088.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/be3xtefq3z3y.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/BlueFeathers.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/Cachy depths 5K.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/DarkStreaks.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/Dead Space (Remake) Screenshot 2024.09.10 - 01.00.19.63.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/Dimensions.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/Dracula.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/e8ssljkntvmy.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/eiznhxxoftde1.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/Elden Ring Screenshot 2024.08.02 - 21.37.44.84.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/Elden Ring Screenshot 2024.08.03 - 17.31.53.58.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/Elden Ring Screenshot 2024.08.03 - 17.32.02.21.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/Elden Ring Screenshot 2024.08.03 - 20.08.08.03.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/Elden Ring Screenshot 2024.08.04 - 13.37.11.38.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/Elden Ring Screenshot 2024.08.04 - 21.20.40.48.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/Elden Ring Screenshot 2024.08.04 - 21.45.18.80.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/Elden Ring Screenshot 2024.08.04 - 21.46.01.47.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/Elden Ring Screenshot 2024.08.07 - 02.01.07.94.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/fqq781ici4ie1.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/p3uhyl5z9ub01.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/Risk of Rain.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/s79v0pv9c1y01.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/Untitled design.png -preload = /mnt/m.2_ssd/Linux/Wallpapers/3840-x-2160-doom-the-dark-ages-v0-x2ppoyuknlse1.webp -preload = /mnt/m.2_ssd/Linux/Wallpapers/3840x2160-landscapes-volume-1-v0-c9ndhnr6b0te1.webp -preload = /mnt/m.2_ssd/Linux/Wallpapers/frozen-warthog-by-jeremy-cook-halo-mcc-3840x2160-v0-epkax6k90whe1.webp -preload = /mnt/m.2_ssd/Linux/Wallpapers/iv9elw3twuz61.webp -preload = /mnt/m.2_ssd/Linux/Wallpapers/landscape-illustrations-3840x2160-v0-6u9wxr8ecqae1.webp -preload = /mnt/m.2_ssd/Linux/Wallpapers/minimalistic-wallpapers-3840x2160-v0-qaj9e6lgtjfe1.webp -preload = /mnt/m.2_ssd/Linux/Wallpapers/rrml8yxhl7q61.webp -preload = /mnt/m.2_ssd/Linux/Wallpapers/some-cool-wallpapers-v0-9gay3iib47da1.webp -preload = /mnt/m.2_ssd/Linux/Wallpapers/some-cool-wallpapers-v0-zpf6isra47da1.webp -preload = /mnt/m.2_ssd/Linux/Wallpapers/world-of-cybernetics-3840x2160-v0-f28kvbmt7lde1.webp -preload = /mnt/m.2_ssd/Linux/Wallpapers/world-of-cybernetics-3840x2160-v0-yts28kew7lde1.webp -wallpaper = diff --git a/airootfs/etc/skel/.config/hypr/workspaces.conf b/airootfs/etc/skel/.config/hypr/workspaces.conf deleted file mode 100755 index e69de29..0000000 diff --git a/airootfs/etc/skel/.config/kitty/kitty.conf b/airootfs/etc/skel/.config/kitty/kitty.conf new file mode 100644 index 0000000..f8a4dae --- /dev/null +++ b/airootfs/etc/skel/.config/kitty/kitty.conf @@ -0,0 +1,9 @@ +# SimulationOS - kitty +font_family JetBrainsMono Nerd Font +font_size 11.0 +background_opacity 0.92 +window_padding_width 6 +scrollback_lines 10000 +enable_audio_bell no +confirm_os_window_close 0 +cursor_shape beam diff --git a/airootfs/etc/skel/.config/mako/config b/airootfs/etc/skel/.config/mako/config new file mode 100644 index 0000000..9e3aca7 --- /dev/null +++ b/airootfs/etc/skel/.config/mako/config @@ -0,0 +1,16 @@ +# SimulationOS - mako notification daemon +font=Fira Sans 10 +background-color=#14161ae6 +text-color=#e6e6e6 +border-color=#1793d1 +border-size=2 +border-radius=8 +padding=10 +margin=8 +default-timeout=6000 +anchor=top-right +width=360 + +[urgency=critical] +border-color=#c0392b +default-timeout=0 diff --git a/airootfs/etc/skel/.config/waybar/config b/airootfs/etc/skel/.config/waybar/config deleted file mode 100755 index 4a581af..0000000 --- a/airootfs/etc/skel/.config/waybar/config +++ /dev/null @@ -1,369 +0,0 @@ -{ - // ------------------------------------------------------------------------- - // Global configuration with hover groups - // ------------------------------------------------------------------------- - - "layer": "top", - "position": "top", - "margin-left": 10, - "margin-bottom": 0, - "margin-right": 10, - "spacing": 5, - - "modules-left": [ - "hyprland/workspaces", -// "hyprland/window", - "custom/spotify", - "custom/cava" - ], - "modules-center": [ - "group/clock", - ], - "modules-right": [ - "group/hardware", - "group/system", - "group/power", - //"custom/electricity", - "pulseaudio", - "network", - "tray" - ], - - // ------------------------------------------------------------------------- - // Groups configuration for hover functionality - // ------------------------------------------------------------------------- - - - "group/clock":{ - - "orientation": "horizontal", - "drawer": { - "transition-duration": 300, - "children-class": "clock-weather-child", - "transition-left-to-right": false - }, - "modules": [ - "clock", - //"custom/weather", - "temperature", - "clock#2" - ] - }, - - "group/power": { - "orientation": "horizontal", - "drawer": { - "transition-duration": 300, - "children-class": "power-child", - "transition-left-to-right": false - }, - "modules": [ - "battery", - "custom/network_traffic", - "custom/electricity" - ] -}, - - "group/network": { - "orientation": "horizontal", - "drawer": { - "transition-duration": 300, - "children-class": "power-child", - "transition-left-to-right": false - }, - "modules": [ - ] -}, - - "group/hardware": { - "orientation": "horizontal", - "drawer": { - "transition-duration": 300, - "children-class": "hardware-child", - "transition-left-to-right": false - }, - "modules": [ - "custom/cpufreq", - "custom/cpu-temp", - "custom/gpu-temp", - "custom/gamemode" - ] - }, - - "group/system": { - "orientation": "horizontal", - "drawer": { - "transition-duration": 300, - "children-class": "system-child", - "transition-left-to-right": false - }, - "modules": [ - "memory", - "custom/network_traffic", - "custom/recorder", - "cpu", - "custom/storage" - ] - }, - - // ------------------------------------------------------------------------- - // Individual module configurations - // ------------------------------------------------------------------------- - "hyprland/window": { - "format": "{}", - "icon":true, - "icon-size" : 20 - }, - "custom/network_traffic": { - "exec": "~/.config/waybar/modules/network_traffic.sh", - "return-type": "json", - "format-ethernet": "{icon} {ifname} ⇣{bandwidthDownBytes} ⇡{bandwidthUpBytes}", // optional -}, - "custom/cava": { - "format": "{}", - "exec": "~/.config/waybar/modules/cava.sh" - }, - - "custom/gamemode": { - "format": "{}", - "return-type": "", - "interval": 2, - "exec": "~/.config/waybar/modules/gamemode.sh status 2>/dev/null", - "on-click": "~/.config/waybar/modules/gamemode.sh toggle 2>/dev/null", - "signal": 8, - "max-length": 10, - "escape": true - }, - - "custom/cpu-temp": { - "exec": "~/.config/waybar/modules/cpu-temp.sh", - "return-type": "json", - "interval": 5, - "format": "{}", - "on-click": "sensors", - "on-click-right": "kitty -e watch -n 1 sensors" - }, - - "custom/gpu-temp": { - "exec": "~/.config/waybar/modules/gpu-temp.sh", - "return-type": "json", - "interval": 5, - "format": "{}", - "on-click": "nvidia-smi", - "on-click-right": "kitty -e watch -n 1 nvidia-smi" - }, - - "memory": { - "interval": 30, - "format": " {used:0.2f} / {total:0.0f} GB", - "on-click": "kitty -e btop" - }, - - "cpu": { - "interval": 1, - "format": " {max_frequency}GHz | {usage:2}%", - "format-alt": " {usage:2}%", - "max-length": 13, - "min-length": 13, - "tooltip": true, - "tooltip-format": "CPU Usage: {usage}%\nFrequency: {max_frequency}GHz\nLoad: {load}" - }, - - "custom/storage": { - "format": " {}", - "format-alt": "{percentage}% ", - "format-alt-click": "click-right", - "return-type": "json", - "interval": 60, - "exec": "~/.config/waybar/modules/storage.sh" - }, - - "disk": { - "interval": 30, - "format": " {percentage_used}%", - "path": "/" - }, - - "custom/cpufreq": { - "exec": "~/.config/waybar/modules/cpufreq.sh", - "interval": 10, - "format": "{}", - "on-click": "~/.config/waybar/modules/cpufreq.sh toggle", - "on-click-right": "~/.config/waybar/modules/refresh-rate.sh toggle", - "on-click-middle": "~/.config/waybar/modules/cpufreq.sh reset", - "tooltip": true, - "tooltip-format": "CPU Governor\nLeft-click: Change Current Mode ⚡\nRight-click: Change Refresh Rate 🔋\nMiddle-click: Reset" - }, - - "battery": { - "interval": 2, - "states": { - "good": 95, - "warning": 30, - "critical": 15 - }, - "format": "{icon} {capacity}%", - "format-charging": " {capacity}%", - "format-plugged": " {capacity}%", - "format-icons": ["", "", "", "", "" ], - }, - - "custom/electricity": { - "interval": 2, - "exec": "~/.config/waybar/modules/power_monitor.sh", - "format": "⚡ {}", - "tooltip": true, - "on-click": "kitty --class 'Power Details' \"$(~/.config/waybar/modules/power_details.sh)\"", - "on-click-right": "kitty --class 'System Power' \"$(~/.config/waybar/modules/system_power.sh)\"", - "return-type": "json" - }, - - "network": { - "format-wifi": " {essid} ({signalStrength}%)", - "format-ethernet": "󰲝 ", - "format-linked": "{ifname} (No IP) ", - "format": "", - "format-disconnected": "󰲜", - "format-alt": "{ifname}: {ipaddr}/{cidr} ", - "on-click": "wl-copy $(ip address show up scope global | grep inet | head -n1 | cut -d/ -f 1 | tr -d [:space:] | cut -c5-)", - "on-click-right": "wl-copy $(ip address show up scope global | grep inet6 | head -n1 | cut -d/ -f 1 | tr -d [:space:] | cut -c6-)", - "tooltip-format": " {bandwidthUpBits}  {bandwidthDownBits}\n{ifname} \n{ipaddr}/{cidr}\n", - "tooltip-format-wifi": " {essid} {frequency}MHz\nStrength: {signaldBm}dBm ({signalStrength}%)\nIP: {ipaddr}/{cidr}\n {bandwidthUpBits}  {bandwidthDownBits}", - "interval": 10 - }, - - "custom/screenshot_t": { - "format": " ", - "on-click": "~/.config/hypr/scripts/manage_wallpaper.sh", - "on-click-right": "~/.config/hypr/scripts/screenshot_area" - }, - - "pulseaudio": { - "scroll-step": 3, // %, can be a float - "format": "{icon} {volume}% {format_source}", - "format-bluetooth": "{volume}% {icon} {format_source}", - "format-bluetooth-muted": " {icon} {format_source}", - "format-muted": " {format_source}", - //"format-source": "{volume}% ", - //"format-source-muted": "", - "format-source": "", - "format-source-muted": "", - "format-icons": { - "headphone": "", - "hands-free": "", - "headset": "", - "phone": "", - "portable": "", - "car": "", - "default": ["", "", ""] - }, - "on-click": "pavucontrol", - "on-click-right": "amixer sset Master toggle" - }, - - "custom/spotify": { - "exec": "~/.config/waybar/mediaplayer.py", - "format": "{} 🎜", - "return-type": "json", - "on-click": "playerctl play-pause", - "on-scroll-up": "playerctl next", - "on-scroll-down": "playerctl previous" - }, - - "clock#date": { - "format": "󰥔 {:%I:%M \n %e %b}", - "tooltip-format": "{:%Y %B}\n{calendar}", - "today-format": "{}", - "on-click": "~/.config/hypr/scripts/manage_wallpaper.sh", - "on-click-right": "~/.config/hypr/scripts/screenshot_area" - }, - - "clock#1": { - "format": " {:%a}", - "tooltip": false, - "on-click": "gsimplecal" - }, - - "clock#2": { - "format": " {:%Y-%m-%d}", - "tooltip-format": "{:%Y %B %A}", - "tooltip": true, - // "on-click": "~/.scripts/Acer/PredatorSense/rgbkb/rgb_random.py", - "on-click": "swaync-client -t", - "on-click-middle": "~/.scripts/Acer/PredatorSense/rgbkb/rgbkb.service.sh", - }, - - "clock": { - "format": " {:%I:%M %p}", - "tooltip": false, - "on-click-middle": "gsimplecal", - "on-click-right": "~/.config/hypr/scripts/screenshot_area", - "on-click": "~/.config/hypr/scripts/manage_wallpaper.sh" - - }, - - - "custom/recorder": { - "exec": "~/.config/waybar/modules/record-status.sh", - "interval": 1, - "on-click": "~/.config/waybar/modules/toggle-record.sh", - "return-type": "json" - } - }, - - - "temperature": { - // "thermal-zone": 1, - "interval": 4, - //"hwmon-path": "/sys/class/hwmon/hwmon3/temp1_input", - "critical-threshold": 60, - // "format-critical": " {temperatureC}°C", - "format-critical": " {temperatureC}°C", - "format": "{icon} {temperatureC}°C", - "format-icons": ["", "", ""], - "max-length": 7, - "min-length": 7, - "on-click": "~/.scripts/Acer/PredatorSense/rgbkb/rgb_random.py", - "on-click-middle": "~/.scripts/Acer/PredatorSense/rgbkb/rgbkb.service.sh", - }, - - - - - - - - - - - - "custom/weather": { - "format": "{}", - "format-alt": "{alt}: {}", - "format-alt-click": "click-right", - "interval": 3600, - "exec": "curl -s 'https://wttr.in/Baghdad?format=1&m'", - "exec-if": "ping wttr.in -c1", - "on-click": "~/.scripts/Acer/PredatorSense/rgbkb/rgb_random.py", - "on-click-middle": "~/.scripts/Acer/PredatorSense/rgbkb/rgbkb.service.sh", - "refresh-on-click": true - }, - - "hyprland/workspaces": { - "all-outputs": true, - "format": "{name}", - "format-icons": { - "1": "一", "2": "二", "3": "三", "4": "四", "5": "五", - "6": "六", "7": "七", "8": "八", "9": "九", "10": "十" - }, - "on-scroll-up": "hyprctl dispatch workspace e+1 1>/dev/null", - "on-scroll-down": "hyprctl dispatch workspace e-1 1>/dev/null", - "sort-by-number": true, - "active-only": false - }, - - "tray": { - "icon-size": 15, - "spacing": 5 - } -} diff --git a/airootfs/etc/skel/.config/waybar/config.jsonc b/airootfs/etc/skel/.config/waybar/config.jsonc new file mode 100644 index 0000000..a997daa --- /dev/null +++ b/airootfs/etc/skel/.config/waybar/config.jsonc @@ -0,0 +1,86 @@ +// SimulationOS - Waybar +// +// Built-in modules only, plus one custom module that calls simos-powermenu +// (shipped in airootfs/usr/local/bin). Nothing here depends on an external +// helper script, so a missing script can never blank the bar. +{ + "layer": "top", + "position": "top", + "height": 34, + "spacing": 6, + + "modules-left": ["hyprland/workspaces", "hyprland/submap"], + "modules-center": ["hyprland/window"], + "modules-right": ["tray", "pulseaudio", "network", "cpu", "memory", "temperature", "battery", "clock", "custom/power"], + + "hyprland/workspaces": { + "format": "{id}", + "on-click": "activate", + "all-outputs": true + }, + + "hyprland/window": { + "format": "{title}", + "max-length": 70, + "separate-outputs": true + }, + + "tray": { + "icon-size": 16, + "spacing": 8 + }, + + "pulseaudio": { + "format": "{icon} {volume}%", + "format-muted": "󰝟 muted", + "format-icons": { "default": ["󰕿", "󰖀", "󰕾"] }, + "on-click": "pavucontrol", + "scroll-step": 5 + }, + + "network": { + "format-wifi": "󰖩 {essid}", + "format-ethernet": "󰈀 {ipaddr}", + "format-linked": "󰈀 no IP", + "format-disconnected": "󰖪 offline", + "tooltip-format": "{ifname} via {gwaddr}", + "on-click": "nm-connection-editor" + }, + + "cpu": { + "format": "󰻠 {usage}%", + "interval": 5 + }, + + "memory": { + "format": "󰍛 {percentage}%", + "interval": 5 + }, + + "temperature": { + "critical-threshold": 82, + "format": "{icon} {temperatureC}°C", + "format-icons": ["", "", ""] + }, + + "battery": { + "states": { "warning": 25, "critical": 10 }, + "format": "{icon} {capacity}%", + "format-charging": "󰂄 {capacity}%", + "format-plugged": "󰚥 {capacity}%", + "format-icons": ["󰁺", "󰁼", "󰁾", "󰂀", "󰂂"], + "tooltip-format": "{timeTo}" + }, + + "clock": { + "format": "󰥔 {:%H:%M}", + "format-alt": "󰃭 {:%a %d %b %Y}", + "tooltip-format": "{calendar}" + }, + + "custom/power": { + "format": "󰐥", + "tooltip": false, + "on-click": "simos-powermenu" + } +} diff --git a/airootfs/etc/skel/.config/waybar/mediaplayer.py b/airootfs/etc/skel/.config/waybar/mediaplayer.py deleted file mode 100755 index 7404f48..0000000 --- a/airootfs/etc/skel/.config/waybar/mediaplayer.py +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/env python3 -import argparse -import logging -import sys -import signal -import gi -import json -gi.require_version('Playerctl', '2.0') -from gi.repository import Playerctl, GLib - -logger = logging.getLogger(__name__) - - -def write_output(text, player): - logger.info('Writing output') - - output = {'text': text, - 'class': 'custom-' + player.props.player_name, - 'alt': player.props.player_name} - - sys.stdout.write(json.dumps(output) + '\n') - sys.stdout.flush() - - -def on_play(player, status, manager): - logger.info('Received new playback status') - on_metadata(player, player.props.metadata, manager) - - -def on_metadata(player, metadata, manager): - logger.info('Received new metadata') - track_info = '' - - if player.props.player_name == 'spotify' and \ - 'mpris:trackid' in metadata.keys() and \ - ':ad:' in player.props.metadata['mpris:trackid']: - track_info = 'AD PLAYING' - elif player.get_artist() != '' and player.get_title() != '': - track_info = '{artist} - {title}'.format(artist=player.get_artist(), - title=player.get_title()) - else: - track_info = player.get_title() - - if player.props.status != 'Playing' and track_info: - track_info = ' ' + track_info - write_output(track_info, player) - - -def on_player_appeared(manager, player, selected_player=None): - if player is not None and (selected_player is None or player.name == selected_player): - init_player(manager, player) - else: - logger.debug("New player appeared, but it's not the selected player, skipping") - - -def on_player_vanished(manager, player): - logger.info('Player has vanished') - sys.stdout.write('\n') - sys.stdout.flush() - - -def init_player(manager, name): - logger.debug('Initialize player: {player}'.format(player=name.name)) - player = Playerctl.Player.new_from_name(name) - player.connect('playback-status', on_play, manager) - player.connect('metadata', on_metadata, manager) - manager.manage_player(player) - on_metadata(player, player.props.metadata, manager) - - -def signal_handler(sig, frame): - logger.debug('Received signal to stop, exiting') - sys.stdout.write('\n') - sys.stdout.flush() - # loop.quit() - sys.exit(0) - - -def parse_arguments(): - parser = argparse.ArgumentParser() - - # Increase verbosity with every occurance of -v - parser.add_argument('-v', '--verbose', action='count', default=0) - - # Define for which player we're listening - parser.add_argument('--player') - - return parser.parse_args() - - -def main(): - arguments = parse_arguments() - - # Initialize logging - logging.basicConfig(stream=sys.stderr, level=logging.DEBUG, - format='%(name)s %(levelname)s %(message)s') - - # Logging is set by default to WARN and higher. - # With every occurrence of -v it's lowered by one - logger.setLevel(max((3 - arguments.verbose) * 10, 0)) - - # Log the sent command line arguments - logger.debug('Arguments received {}'.format(vars(arguments))) - - manager = Playerctl.PlayerManager() - loop = GLib.MainLoop() - - manager.connect('name-appeared', lambda *args: on_player_appeared(*args, arguments.player)) - manager.connect('player-vanished', on_player_vanished) - - signal.signal(signal.SIGINT, signal_handler) - signal.signal(signal.SIGTERM, signal_handler) - - for player in manager.props.player_names: - if arguments.player is not None and arguments.player != player.name: - logger.debug('{player} is not the filtered player, skipping it' - .format(player=player.name) - ) - continue - - init_player(manager, player) - - loop.run() - - -if __name__ == '__main__': - main() diff --git a/airootfs/etc/skel/.config/waybar/modules/cava.sh b/airootfs/etc/skel/.config/waybar/modules/cava.sh deleted file mode 100755 index 14ebaca..0000000 --- a/airootfs/etc/skel/.config/waybar/modules/cava.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/sh -trap 'exit 0' PIPE TERM INT - -# Create vertical bars like terminal cava -bar="▁▂▃▄▅▆▇█" -dict="s/;//g;" -i=0 -while [ $i -lt 8 ]; do - dict="${dict}s/$i/${bar:$i:1}/g;" - i=$((i+1)) -done - -# Add spaces between bars for terminal look -dict="${dict}s/\(.\)/\1 /g;" - -# Write cava config for raw output -echo "[general] -bars = 12 -[output] -method = raw -raw_target = /dev/stdout -data_format = ascii -ascii_max_range = 7" > /tmp/cava_config - -check_counter=0 -current_state="stopped" - -cava -p /tmp/cava_config 2>/dev/null | while read -r line; do - check_counter=$((check_counter + 1)) - if [ $check_counter -ge 20 ]; then - if pactl list sink-inputs 2>/dev/null | grep -q "Sink Input"; then - current_state="playing" - else - current_state="stopped" - fi - check_counter=0 - fi - - if [ "$current_state" = "playing" ]; then - echo "$line" | sed "$dict" 2>/dev/null || exit 0 - else - echo "" 2>/dev/null || exit 0 - fi -done diff --git a/airootfs/etc/skel/.config/waybar/modules/cpu-temp.sh b/airootfs/etc/skel/.config/waybar/modules/cpu-temp.sh deleted file mode 100755 index 8eacc1c..0000000 --- a/airootfs/etc/skel/.config/waybar/modules/cpu-temp.sh +++ /dev/null @@ -1,160 +0,0 @@ -#!/bin/bash -# ~/.config/waybar/modules/cpu-temp-fan.sh -# Combined CPU temperature and fan speed monitor for Waybar - -# SysFS path for fan speed (from your Predator Sense script) -FAN_SYSFS_PATH="/sys/module/linuwu_sense/drivers/platform:acer-wmi/acer-wmi/predator_sense/fan_speed" - -# Function to get CPU temperature -get_cpu_temp() { - local temp="" - - # Method 1: Use sensors command to get Package id 0 temperature - if command -v sensors &> /dev/null; then - temp=$(sensors 2>/dev/null | grep "Package id 0" | awk '{print $4}' | sed 's/+//g' | sed 's/°C//g' | cut -d'.' -f1) - fi - - # Method 2: Fallback to hwmon9 (coretemp) temp1_input which corresponds to Package id 0 - if [ -z "$temp" ] && [ -f "/sys/class/hwmon/hwmon9/temp1_input" ]; then - temp_raw=$(cat /sys/class/hwmon/hwmon9/temp1_input 2>/dev/null) - if [ -n "$temp_raw" ]; then - temp=$((temp_raw / 1000)) - fi - fi - - # Method 3: Alternative hwmon path fallback - if [ -z "$temp" ]; then - for hwmon in /sys/class/hwmon/hwmon*/name; do - if [ "$(cat "$hwmon" 2>/dev/null)" = "coretemp" ]; then - hwmon_dir=$(dirname "$hwmon") - if [ -f "$hwmon_dir/temp1_input" ]; then - temp_raw=$(cat "$hwmon_dir/temp1_input" 2>/dev/null) - if [ -n "$temp_raw" ]; then - temp=$((temp_raw / 1000)) - break - fi - fi - fi - done - fi - - # Remove any whitespace/newlines - temp=$(echo "$temp" | tr -d ' \n\r') - echo "$temp" -} - -# Function to get CPU fan speed percentage -get_cpu_fan_speed() { - local fan_speed="" - - # Check if the fan speed sysfs path exists - if [ -f "$FAN_SYSFS_PATH" ]; then - # Read the fan speed value (format: "cpu_speed,gpu_speed") - fan_data=$(cat "$FAN_SYSFS_PATH" 2>/dev/null) - if [ -n "$fan_data" ]; then - # Extract CPU fan speed (first value before comma) - fan_speed=$(echo "$fan_data" | cut -d',' -f1) - # Handle special case for auto mode (0,0) - if [ "$fan_speed" = "0" ]; then - fan_speed="Auto" - else - fan_speed="${fan_speed}%" - fi - fi - fi - - # Return empty string if no fan data available (instead of "N/A") - echo "$fan_speed" -} - -# Function to determine temperature class and icon -get_temp_status() { - local temp=$1 - - if [ "$temp" -lt 40 ]; then - echo "❄️" "cold" - elif [ "$temp" -lt 60 ]; then - echo "🟢" "good" - elif [ "$temp" -lt 70 ]; then - echo "🟡" "warm" - elif [ "$temp" -lt 80 ]; then - echo "🟠" "hot" - else - echo "🔥" "critical" - fi -} - -# Function to determine fan class -get_fan_status() { - local fan_speed=$1 - - case "$fan_speed" in - "Auto") echo "auto" ;; - "") echo "unknown" ;; # Empty string instead of "N/A" - *%) - # Extract numeric value for percentage-based classification - local speed_num=$(echo "$fan_speed" | sed 's/%//') - if [ "$speed_num" -lt 30 ]; then - echo "low" - elif [ "$speed_num" -lt 60 ]; then - echo "medium" - else - echo "high" - fi - ;; - *) echo "unknown" ;; - esac -} - -# Main execution -main() { - # Get CPU temperature - cpu_temp=$(get_cpu_temp) - - # Get CPU fan speed - cpu_fan=$(get_cpu_fan_speed) - - # Handle case where temperature is not available - if [ -z "$cpu_temp" ] || [ "$cpu_temp" = "0" ]; then - if [ -n "$cpu_fan" ]; then - echo "{\"text\":\"🔍 CPU N/A | 🌀 $cpu_fan\",\"class\":\"unknown\",\"tooltip\":\"CPU temperature not available\"}" - else - echo "{\"text\":\"🔍 CPU N/A\",\"class\":\"unknown\",\"tooltip\":\"CPU temperature not available\"}" - fi - exit 0 - fi - - # Get temperature status - read temp_icon temp_class <<< "$(get_temp_status "$cpu_temp")" - - # Get fan status - fan_class=$(get_fan_status "$cpu_fan") - - # Determine overall class (prioritize temperature for critical situations) - if [ "$temp_class" = "critical" ]; then - overall_class="critical" - elif [ "$temp_class" = "hot" ]; then - overall_class="hot" - elif [ "$temp_class" = "warm" ]; then - overall_class="warm" - elif [ "$fan_class" = "unknown" ]; then - overall_class="unknown" - else - overall_class="good" - fi - - # Format output text - only include fan info if available - if [ -n "$cpu_fan" ]; then - display_text="$temp_icon ${cpu_temp}°C | 🌀 $cpu_fan" - tooltip="CPU Temperature: ${cpu_temp}°C\\nCPU Fan Speed: $cpu_fan" - else - display_text="$temp_icon ${cpu_temp}°C" - tooltip="CPU Temperature: ${cpu_temp}°C\\nCPU Fan Speed: Not available" - fi - - # Output JSON for waybar - echo "{\"text\":\"$display_text\",\"class\":\"$overall_class\",\"tooltip\":\"$tooltip\"}" -} - -# Run main function -main diff --git a/airootfs/etc/skel/.config/waybar/modules/cpufreq.sh b/airootfs/etc/skel/.config/waybar/modules/cpufreq.sh deleted file mode 100755 index eec9755..0000000 --- a/airootfs/etc/skel/.config/waybar/modules/cpufreq.sh +++ /dev/null @@ -1,69 +0,0 @@ -#!/bin/bash -# Get current governor -if [ -f /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor ]; then - GOVERNOR=$(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor) -else - GOVERNOR="unknown" -fi - -# Get current refresh rate from hyprctl -if command -v hyprctl >/dev/null 2>&1; then - REFRESH_RATE=$(hyprctl monitors | grep -E '@[0-9]+\.[0-9]+' | head -1 | sed -n 's/.*@\([0-9]\+\.[0-9]\+\).*/\1/p') - if [ -n "$REFRESH_RATE" ]; then - # Round to nearest integer for cleaner display - REFRESH_RATE=$(printf "%.0f" "$REFRESH_RATE") - REFRESH_DISPLAY=" | 󰹑 ${REFRESH_RATE}Hz" - else - REFRESH_DISPLAY="" - fi -else - REFRESH_DISPLAY="" -fi - -# Handle click actions -case $1 in - toggle) - # Toggle between powersave and performance - if [ "$GOVERNOR" = "powersave" ]; then - sudo -n auto-cpufreq --force performance >/dev/null 2>&1 - else - sudo -n auto-cpufreq --force powersave >/dev/null 2>&1 - fi - ;; - reset) - # Still requires explicit reset command - sudo -n auto-cpufreq --force reset >/dev/null 2>&1 - ;; -esac - -# Re-read governor after potential change -if [ -f /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor ]; then - GOVERNOR=$(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor) -else - GOVERNOR="unknown" -fi - -# Map governor to icon + text with refresh rate -case $GOVERNOR in - "performance") - echo "󰾆 performance${REFRESH_DISPLAY}" - ;; - "powersave") - echo "󰂏 powersave${REFRESH_DISPLAY}" - ;; - "ondemand") - echo "⚖️ ondemand${REFRESH_DISPLAY}" - ;; - "conservative") - echo "🐌 conservative${REFRESH_DISPLAY}" - ;; - "schedutil") - echo "📊 schedutil${REFRESH_DISPLAY}" - ;; - "userspace") - echo "👤 userspace${REFRESH_DISPLAY}" - ;; - *) - echo "❓ $GOVERNOR${REFRESH_DISPLAY}" - ;; -esac diff --git a/airootfs/etc/skel/.config/waybar/modules/debug-temp.sh b/airootfs/etc/skel/.config/waybar/modules/debug-temp.sh deleted file mode 100755 index 7c361ad..0000000 --- a/airootfs/etc/skel/.config/waybar/modules/debug-temp.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/bash -# ~/.config/waybar/modules/debug-temp.sh - -echo "=== Temperature Debug ===" -echo "" - -echo "1. CPU Temperature Methods:" -echo " sensors coretemp:" -sensors coretemp-isa-0000 2>/dev/null | grep "Package id 0" -echo "" - -echo " CPU from sensors (Package id 0):" -cpu_temp=$(sensors coretemp-isa-0000 2>/dev/null | grep "Package id 0" | awk '{print $4}' | sed 's/+//g' | sed 's/°C//g' | cut -d'.' -f1) -echo " Result: '$cpu_temp'" -echo "" - -echo "2. GPU Temperature Methods:" -echo " nvidia-settings:" -nvidia-settings -q gpucoretemp -t 2>/dev/null -echo "" - -echo " nvidia-smi:" -nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader,nounits 2>/dev/null -echo "" - -echo "3. Available hwmon sensors:" -for i in /sys/class/hwmon/hwmon*/name; do - if [ -f "$i" ]; then - echo " $i: $(cat $i 2>/dev/null)" - fi -done -echo "" - -echo "4. Available temperature inputs:" -for i in /sys/class/hwmon/hwmon*/temp*_input; do - if [ -f "$i" ]; then - temp_val=$(cat $i 2>/dev/null) - temp_c=$((temp_val / 1000)) - echo " $i: ${temp_val} (${temp_c}°C)" - fi -done -echo "" - -echo "5. Testing waybar scripts:" -echo " CPU script:" -if [ -f ~/.config/waybar/modules/cpu-temp.sh ]; then - ~/.config/waybar/modules/cpu-temp.sh -else - echo " CPU script not found" -fi -echo "" - -echo " GPU script:" -if [ -f ~/.config/waybar/modules/gpu-temp.sh ]; then - ~/.config/waybar/modules/gpu-temp.sh -else - echo " GPU script not found" -fi diff --git a/airootfs/etc/skel/.config/waybar/modules/gamemode.sh b/airootfs/etc/skel/.config/waybar/modules/gamemode.sh deleted file mode 100755 index ac6378b..0000000 --- a/airootfs/etc/skel/.config/waybar/modules/gamemode.sh +++ /dev/null @@ -1,78 +0,0 @@ -#!/bin/bash -# ____ _ -# / ___| ******* *** ___ ___ ** **_ **| | **_ -# | | * / *` | '_ ` * \ / * \ '_ ` \ / \ / `* |/ * \ -# | |_| | (_| | | | | | | __/ | | | | | (_) | (_| | __/ -# \____|\__,_|_| |_| |_|\___|_| |_| |_|\___/ \__,_|\___| -# -# Enhanced gamemode script with Waybar integration - -CACHE_FILE="$HOME/.cache/gamemode" - -# Function to get current status for Waybar (plain text output like cpufreq) -get_status() { - if [ -f "$CACHE_FILE" ]; then - printf "🎮 ON" - else - printf "🎮 OFF" - fi -} - -# Function to enable gamemode (silent for Waybar) -enable_gamemode() { - if [ -f "$CACHE_FILE" ]; then - return 0 - fi - - hyprctl --batch "\ - keyword animations:enabled 0;\ - keyword decoration:drop_shadow 0;\ - keyword decoration:blur:enabled 0;\ - keyword general:gaps_in 0;\ - keyword general:gaps_out 0;\ - keyword general:border_size 1;\ - keyword decoration:rounding 0" >/dev/null 2>&1 - - touch "$CACHE_FILE" - notify-send "Gamemode" "Activated" >/dev/null 2>&1 & -} - -# Function to disable gamemode (silent for Waybar) -disable_gamemode() { - if [ ! -f "$CACHE_FILE" ]; then - return 0 - fi - - hyprctl reload >/dev/null 2>&1 - rm -f "$CACHE_FILE" - notify-send "Gamemode" "Deactivated" >/dev/null 2>&1 & -} - -# Function for toggle -toggle_gamemode() { - if [ -f "$CACHE_FILE" ]; then - disable_gamemode - else - enable_gamemode - fi -} - -# Handle command line arguments -case "$1" in - "status") - get_status - ;; - "enable") - enable_gamemode - ;; - "disable") - disable_gamemode - ;; - "toggle") - toggle_gamemode - ;; - *) - echo "Usage: $0 {enable|disable|toggle|status}" - exit 1 - ;; -esac diff --git a/airootfs/etc/skel/.config/waybar/modules/gpu-temp.sh b/airootfs/etc/skel/.config/waybar/modules/gpu-temp.sh deleted file mode 100755 index 458a97c..0000000 --- a/airootfs/etc/skel/.config/waybar/modules/gpu-temp.sh +++ /dev/null @@ -1,93 +0,0 @@ -#!/bin/bash -# ~/.config/waybar/modules/gpu-temp-fan.sh -# Combined GPU temperature and fan speed monitor for Waybar - -# SysFS path for fan speed (from your Predator Sense script) -FAN_SYSFS_PATH="/sys/module/linuwu_sense/drivers/platform:acer-wmi/acer-wmi/predator_sense/fan_speed" - -# Get GPU temperature -get_gpu_temp() { - local temp="" - - # Try nvidia-smi first (faster and doesn't require X) - if command -v nvidia-smi &>/dev/null; then - temp=$(nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader,nounits 2>/dev/null | head -1 | tr -d '\n') - fi - - # Fallback to nvidia-settings if needed - if [[ -z "$temp" || "$temp" == "0" ]] && command -v nvidia-settings &>/dev/null; then - temp=$(DISPLAY=:0 nvidia-settings -q gpucoretemp -t 2>/dev/null | head -1 | tr -d '\n') - fi - - echo "$temp" -} - -# Get GPU fan speed percentage -get_gpu_fan_speed() { - local fan_speed="" - - # Check if the fan speed sysfs path exists - if [ -f "$FAN_SYSFS_PATH" ]; then - # Read the fan speed value (format: "cpu_speed,gpu_speed") - fan_data=$(cat "$FAN_SYSFS_PATH" 2>/dev/null) - if [ -n "$fan_data" ]; then - # Extract GPU fan speed (second value after comma) - fan_speed=$(echo "$fan_data" | cut -d',' -f2) - # Handle special case for auto mode (0,0) - if [ "$fan_speed" = "0" ]; then - fan_speed="Auto" - else - fan_speed="${fan_speed}%" - fi - fi - fi - - # Return empty string if no fan data available (instead of "N/A") - echo "$fan_speed" -} - -# Get status based on temperature -get_status() { - local temp=$1 - - if [[ $temp -lt 50 ]]; then - echo "❄️" "cold" - elif [[ $temp -lt 70 ]]; then - echo "🟢" "good" - elif [[ $temp -lt 80 ]]; then - echo "🟡" "warm" - elif [[ $temp -lt 85 ]]; then - echo "🟠" "hot" - else - echo "🔥" "critical" - fi -} - -# Main execution -temp=$(get_gpu_temp) -fan=$(get_gpu_fan_speed) - -# Handle missing temperature data -if [[ -z "$temp" || "$temp" == "0" ]]; then - if [ -n "$fan" ]; then - echo "{\"text\":\"🔍 GPU N/A | 🌀 $fan\",\"class\":\"unknown\",\"tooltip\":\"GPU temperature not available\"}" - else - echo "{\"text\":\"🔍 GPU N/A\",\"class\":\"unknown\",\"tooltip\":\"GPU temperature not available\"}" - fi - exit 0 -fi - -# Get status -read icon class <<< "$(get_status "$temp")" - -# Format output text - only include fan info if available -if [ -n "$fan" ]; then - display_text="$icon ${temp}°C | 🌀 $fan" - tooltip="GPU: ${temp}°C\\nGPU Fan: $fan" -else - display_text="$icon ${temp}°C" - tooltip="GPU: ${temp}°C\\nGPU Fan: Not available" -fi - -# Output JSON for waybar -echo "{\"text\":\"$display_text\",\"class\":\"$class\",\"tooltip\":\"$tooltip\"}" diff --git a/airootfs/etc/skel/.config/waybar/modules/network_traffic.sh b/airootfs/etc/skel/.config/waybar/modules/network_traffic.sh deleted file mode 100755 index 4a68cc8..0000000 --- a/airootfs/etc/skel/.config/waybar/modules/network_traffic.sh +++ /dev/null @@ -1,110 +0,0 @@ -#!/bin/bash - -# network_traffic.sh [-tPOLLING_INTERVAL] [NETWORK_INTERFACE...] - -getopts t: __ && shift -isecs=${OPTARG:-1} -ifaces=($@) -: ${rate_max:=1000000} # maximum transfer rate for {percent}, can be overridden setting the env var - -# `snore` adapted from https://blog.dhampir.no/content/sleeping-without-a-subprocess-in-bash-and-how-to-sleep-forever -# without MacOS workaround, TODO: with _snore_fd initialized separatedly, also i dont touch IFS so dont bother with it -snore() { - local IFS - [[ -n "${_snore_fd:-}" ]] || { exec {_snore_fd}<> <(:); } 2>/dev/null - read ${1:+-t "$1"} -u $_snore_fd || : -} - -human_readable() { - local hrunits=( B K M G T P ) - local ndigits=${#1} - local idxunit=$(( (2 + ndigits) / 3 - 1)) - local lentrim=$(( ndigits - (idxunit * 3 ) )) - echo ${1::$lentrim}${hrunits[$idxunit]} -} - -exit_err() { - printf '{"text": "⚠ %s", "tooltip": "%s", "class": "error"}\n' "$@" - exit -} - -if test ${#ifaces[@]} -gt 0; then -# sanity check the interface names - for iface in ${ifaces[@]}; do - test -h "/sys/class/net/${iface}" || exit_err "${iface}" "${iface} is not an existing network interface name" - done -else -# default to all interfaces except `lo` - ifaces=(/sys/class/net/*) - ifaces=(${ifaces[@]##*/}) - ifaces=(${ifaces[@]^(eth|wlan|enp|wlp|eno)}) -fi - -# sanity check polling interval -if test ${isecs} -lt 1; then - exit_err "${isecs}" "${isecs} is not a valid polling interval" -fi -# NOTE: `snore` would take a decimal interval but bash arithmetic does not -#if test $(echo "${isecs} >= 0.2" |bc) -eq 0; then -# exit_err "${isecs}" "${isecs} is not a valid polling interval" -#fi - -# NOTE: `/proc/net/dev` format is: -# interface: -# RX bytes packets errs drop fifo frame compressed multicast -# TX bytes packets errs drop fifo colls carrier compressed - -# NOTE: array items are: -# 0=rx_bytes 1=rx_packets 2=rx_errs 3=rx_drop -# 4=tx_bytes 5=tx_packets 6=tx_errs 7=tx_drop -for iface in ${ifaces[@]} aggregate; do - declare -a traffic_prev_${iface} traffic_curr_${iface} traffic_delt_${iface} - declare -n traffic_prev=traffic_prev_${iface} - declare -n traffic_curr=traffic_curr_${iface} - declare -n traffic_delt=traffic_delt_${iface} - traffic_prev=( 0 0 0 0 0 0 0 0 ) - traffic_curr=( 0 0 0 0 0 0 0 0 ) - traffic_delt=( 0 0 0 0 0 0 0 0 ) -done - -# TODO: rearrange the loop, do not show bogus on first iteration -while snore ${isecs} ;do - tooltip="" - traffic_delt_aggregate=( 0 0 0 0 0 0 0 0 ) - - readarray -s2 proc_net_dev /dev/null; then - battery_device=$(upower -e | grep -i bat | head -1) - if [[ -n "$battery_device" ]]; then - upower -i "$battery_device" | grep -E "state|energy|voltage|percentage|time to|power" | sed 's/^ *//' - else - echo "No battery device found" - fi -else - echo "upower not installed" -fi - -echo -echo "=== POWER SUPPLY FILES ===" -echo - -# Raw power supply information -for bat in /sys/class/power_supply/BAT*; do - if [[ -d "$bat" ]]; then - echo "Battery: $(basename "$bat")" - if [[ -f "$bat/power_now" ]]; then - power_uw=$(cat "$bat/power_now" 2>/dev/null) - power_w=$(awk "BEGIN {printf \"%.2f\", $power_uw / 1000000}" 2>/dev/null) - echo " Power Now: $power_uw µW ($power_w W)" - fi - [[ -f "$bat/voltage_now" ]] && echo " Voltage: $(cat "$bat/voltage_now" 2>/dev/null) µV" - [[ -f "$bat/current_now" ]] && echo " Current: $(cat "$bat/current_now" 2>/dev/null) µA" - [[ -f "$bat/status" ]] && echo " Status: $(cat "$bat/status" 2>/dev/null)" - [[ -f "$bat/capacity" ]] && echo " Capacity: $(cat "$bat/capacity" 2>/dev/null)%" - echo - fi -done - - diff --git a/airootfs/etc/skel/.config/waybar/modules/power_monitor.sh b/airootfs/etc/skel/.config/waybar/modules/power_monitor.sh deleted file mode 100755 index 278466f..0000000 --- a/airootfs/etc/skel/.config/waybar/modules/power_monitor.sh +++ /dev/null @@ -1,179 +0,0 @@ -#!/bin/bash -# ~/.config/waybar/scripts/power_monitor.sh -# Portable power monitoring script for waybar - -# Get battery voltage information from any available battery -get_battery_voltage() { - # Use the same approach as your working version - find first available battery - local battery_dir=$(ls -d /sys/class/power_supply/BAT* 2>/dev/null | head -1) - - if [[ -d "$battery_dir" ]]; then - # Try voltage_now first (like your working version) - local voltage_now=$(cat "$battery_dir/voltage_now" 2>/dev/null) - if [[ -n "$voltage_now" && "$voltage_now" -gt 0 ]]; then - local voltage_v=$(awk "BEGIN {printf \"%.2f\", $voltage_now / 1000000}") - echo "$voltage_v V" - return - fi - - # Try voltage_avg as alternative - local voltage_avg=$(cat "$battery_dir/voltage_avg" 2>/dev/null) - if [[ -n "$voltage_avg" && "$voltage_avg" -gt 0 ]]; then - local voltage_v=$(awk "BEGIN {printf \"%.2f\", $voltage_avg / 1000000}") - echo "$voltage_v V" - return - fi - - # Fallback to design voltage - local design_voltage=$(cat "$battery_dir/voltage_min_design" 2>/dev/null) - if [[ -n "$design_voltage" && "$design_voltage" -gt 0 ]]; then - local voltage_v=$(awk "BEGIN {printf \"%.2f\", $design_voltage / 1000000}") - echo "$voltage_v V (design)" - return - fi - - # Try alternative design voltage file - local design_voltage2=$(cat "$battery_dir/voltage_design" 2>/dev/null) - if [[ -n "$design_voltage2" && "$design_voltage2" -gt 0 ]]; then - local voltage_v=$(awk "BEGIN {printf \"%.2f\", $design_voltage2 / 1000000}") - echo "$voltage_v V (design)" - return - fi - fi - - echo "N/A" -} - -# Get power consumption (watts) if available and non-zero -get_power_consumption() { - # Use the same battery finding approach for consistency - local battery_dir=$(ls -d /sys/class/power_supply/BAT* 2>/dev/null | head -1) - - if [[ -d "$battery_dir" ]]; then - # Check for power_now file first (most direct) - if [[ -f "$battery_dir/power_now" ]]; then - local power_now=$(cat "$battery_dir/power_now" 2>/dev/null) - if [[ -n "$power_now" && "$power_now" != "0" && "$power_now" =~ ^-?[0-9]+$ ]]; then - local power_w=$(awk "BEGIN {printf \"%.1f\", $power_now / 1000000}") - echo "${power_w}W" - return - fi - fi - - # Alternative: calculate from current and voltage - if [[ -f "$battery_dir/current_now" ]]; then - local current_now=$(cat "$battery_dir/current_now" 2>/dev/null) - if [[ -n "$current_now" && "$current_now" != "0" && "$current_now" =~ ^-?[0-9]+$ ]]; then - # Get voltage for power calculation - local voltage_now=$(cat "$battery_dir/voltage_now" 2>/dev/null) - if [[ -z "$voltage_now" || "$voltage_now" == "0" ]]; then - voltage_now=$(cat "$battery_dir/voltage_avg" 2>/dev/null) - fi - - if [[ -n "$voltage_now" && "$voltage_now" -gt 0 ]]; then - # Calculate power in watts (current in microamps * voltage in microvolts / 1000000000000) - local power_uw=$(awk "BEGIN {printf \"%.0f\", ($current_now * $voltage_now) / 1000000}") - if [[ "$power_uw" != "0" ]]; then - local power_w=$(awk "BEGIN {printf \"%.1f\", $power_uw / 1000000}") - echo "${power_w}W" - return - fi - fi - fi - fi - fi - - echo "" -} - -# Get battery status from first available battery -get_battery_status() { - local status_file=$(ls /sys/class/power_supply/BAT*/status 2>/dev/null | head -1) - if [[ -f "$status_file" ]]; then - cat "$status_file" 2>/dev/null | tr '[:upper:]' '[:lower:]' - else - echo "unknown" - fi -} - -# Get battery percentage from first available battery -get_battery_percentage() { - local capacity_file=$(ls /sys/class/power_supply/BAT*/capacity 2>/dev/null | head -1) - if [[ -f "$capacity_file" ]]; then - cat "$capacity_file" 2>/dev/null - else - echo "N/A" - fi -} - -# Check if AC adapter is connected (supports various naming conventions) -is_ac_connected() { - # Check standard patterns like your working version - for ac in /sys/class/power_supply/A{C,DP}*; do - if [[ -d "$ac" && -f "$ac/online" ]]; then - [[ $(cat "$ac/online" 2>/dev/null) == "1" ]] && return 0 - fi - done - - # Additional check for ACAD pattern - for ac in /sys/class/power_supply/ACAD*; do - if [[ -d "$ac" && -f "$ac/online" ]]; then - [[ $(cat "$ac/online" 2>/dev/null) == "1" ]] && return 0 - fi - done - - return 1 -} - -# Get battery count for tooltip -get_battery_count() { - local count=$(ls -d /sys/class/power_supply/BAT* 2>/dev/null | wc -l) - echo "$count" -} - -# Main execution -voltage=$(get_battery_voltage) -power=$(get_power_consumption) -status=$(get_battery_status) -percentage=$(get_battery_percentage) -battery_count=$(get_battery_count) - -# Build display text -text="$voltage" -if [[ -n "$power" ]]; then - text="$text | $power" -fi - -# Create detailed tooltip -if is_ac_connected; then - tooltip="🔌 AC Connected" -else - tooltip="🔋 On Battery" -fi - -tooltip="$tooltip | Voltage: $voltage" - -if [[ -n "$power" ]]; then - tooltip="$tooltip | Power: $power" -fi - -tooltip="$tooltip | Battery: ${percentage}% (${status})" - -if [[ "$battery_count" -gt 1 ]]; then - tooltip="$tooltip | ${battery_count} batteries detected" -fi - -# Determine CSS class based on status -css_class="power-monitor" -if is_ac_connected; then - css_class="$css_class ac-connected" -else - css_class="$css_class battery-mode" - # Add low battery warning class - if [[ "$percentage" != "N/A" && "$percentage" -lt 20 ]]; then - css_class="$css_class low-battery" - fi -fi - -# Output JSON for waybar -printf '{"text": "%s", "tooltip": "%s", "class": "%s"}\n' "$text" "$tooltip" "$css_class" diff --git a/airootfs/etc/skel/.config/waybar/modules/record-status.sh b/airootfs/etc/skel/.config/waybar/modules/record-status.sh deleted file mode 100755 index b0bc9da..0000000 --- a/airootfs/etc/skel/.config/waybar/modules/record-status.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -RECORD_PID_FILE="/tmp/wf-recording.pid" - -if [ -f "$RECORD_PID_FILE" ] && kill -0 "$(cat "$RECORD_PID_FILE")" 2>/dev/null; then - echo '{"text": "", "tooltip": "Recording", "class": "recording"}' -else - echo '{"text": " ", "tooltip": "Not recording", "class": "idle"}' -fi diff --git a/airootfs/etc/skel/.config/waybar/modules/refresh-rate.sh b/airootfs/etc/skel/.config/waybar/modules/refresh-rate.sh deleted file mode 100755 index 403493d..0000000 --- a/airootfs/etc/skel/.config/waybar/modules/refresh-rate.sh +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/bash - -CONFIG_FILE="$HOME/.config/hypr/monitors.conf" -MONITOR_NAME="eDP-1" - -# Get current refresh rate from hyprctl -get_current_refresh_rate() { - hyprctl monitors | grep -A 1 "Monitor $MONITOR_NAME" | grep -o '@[0-9]*\.[0-9]*' | sed 's/@//' | head -1 -} - -# Update the config file -update_config_file() { - local target_rate=$1 - - if [ -f "$CONFIG_FILE" ]; then - # Comment out current line and uncomment target line - if [ "$target_rate" = "165" ]; then - sed -i 's/^monitor=eDP-1,2560x1600@165/#&/' "$CONFIG_FILE" - sed -i 's/^#monitor=eDP-1,2560x1600@60/monitor=eDP-1,2560x1600@60/' "$CONFIG_FILE" - else - sed -i 's/^monitor=eDP-1,2560x1600@60/#&/' "$CONFIG_FILE" - sed -i 's/^#monitor=eDP-1,2560x1600@165/monitor=eDP-1,2560x1600@165/' "$CONFIG_FILE" - fi - fi -} - -# Handle click actions -case $1 in - toggle) - # Get current refresh rate - CURRENT_RATE=$(get_current_refresh_rate) - CURRENT_RATE_INT=$(printf "%.0f" "$CURRENT_RATE") - - if [ "$CURRENT_RATE_INT" = "165" ] || [ "$CURRENT_RATE_INT" = "164" ]; then - # Switch to 60Hz - hyprctl keyword monitor "$MONITOR_NAME,2560x1600@60,0x0,1.0" >/dev/null 2>&1 - update_config_file 165 - echo "🔄 Switched to 60Hz" - else - # Switch to 165Hz - hyprctl keyword monitor "$MONITOR_NAME,2560x1600@165,0x0,1.0" >/dev/null 2>&1 - update_config_file 60 - echo "🔄 Switched to 165Hz" - fi - ;; - status) - # Show current refresh rate - CURRENT_RATE=$(get_current_refresh_rate) - CURRENT_RATE_INT=$(printf "%.0f" "$CURRENT_RATE") - - if [ "$CURRENT_RATE_INT" = "165" ] || [ "$CURRENT_RATE_INT" = "164" ]; then - echo "🖥️ ${CURRENT_RATE_INT}Hz" - else - echo "🖥️ ${CURRENT_RATE_INT}Hz" - fi - ;; - *) - # Default: show current status - CURRENT_RATE=$(get_current_refresh_rate) - CURRENT_RATE_INT=$(printf "%.0f" "$CURRENT_RATE") - - if [ "$CURRENT_RATE_INT" = "165" ] || [ "$CURRENT_RATE_INT" = "164" ]; then - echo "🖥️ ${CURRENT_RATE_INT}Hz" - else - echo "🖥️ ${CURRENT_RATE_INT}Hz" - fi - ;; -esac diff --git a/airootfs/etc/skel/.config/waybar/modules/storage.sh b/airootfs/etc/skel/.config/waybar/modules/storage.sh deleted file mode 100755 index 531a6fe..0000000 --- a/airootfs/etc/skel/.config/waybar/modules/storage.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh - -mount="/" -warning=20 -critical=10 - -df -h -P -l "$mount" | awk -v warning=$warning -v critical=$critical ' -/\/.*/ { - text=$4 - text=" "text - tooltip="Filesystem: "$1" \rSize: "$2"\rUsed: "$3"\rAvail: "$4"\rUse%: "$5"\rMounted on: "$6 - use=$5 - exit 0 -} -END { - class="" - gsub(/%$/,"",use) - if ((100 - use) < critical) { - class="critical" - } else if ((100 - use) < warning) { - class="warning" - } - print "{\"text\":\""text"\", \"percentage\":"use",\"tooltip\":\""tooltip"\", \"class\":\""class"\"}" -} -' diff --git a/airootfs/etc/skel/.config/waybar/modules/system_power.sh b/airootfs/etc/skel/.config/waybar/modules/system_power.sh deleted file mode 100755 index a9459e9..0000000 --- a/airootfs/etc/skel/.config/waybar/modules/system_power.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash -# ~/.config/waybar/scripts/system_power.sh - - -echo "=== SYSTEM POWER USAGE ===" -echo - -# Check for powertop -if command -v powertop &> /dev/null; then - echo "Getting system power usage (this may take a few seconds)..." - sudo powertop --dump --quiet --time=1 2>/dev/null | grep -A 10 "Power est" | head -10 - echo -fi - -# CPU frequency and governor -echo "=== CPU INFO ===" -if [[ -f /proc/cpuinfo ]]; then - echo "CPU: $(grep "model name" /proc/cpuinfo | head -1 | cut -d: -f2 | xargs)" -fi - -if [[ -f /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor ]]; then - echo "Governor: $(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor)" -fi - -if [[ -f /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq ]]; then - freq=$(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq) - echo "Frequency: $(awk "BEGIN {printf \"%.2f\", $freq / 1000}")MHz" -fi - -echo -echo "=== THERMAL INFO ===" -# Temperature info -if command -v sensors &> /dev/null; then - sensors | grep -E "(Core|Package|temp)" | head -5 -elif [[ -f /sys/class/thermal/thermal_zone0/temp ]]; then - temp=$(cat /sys/class/thermal/thermal_zone0/temp) - echo "CPU Temp: $(awk "BEGIN {printf \"%.1f\", $temp / 1000}")°C" -fi - -echo -echo "=== LOAD AVERAGE ===" -echo "Load: $(uptime | awk -F'load average:' '{print $2}' | xargs)" - -# Memory usage -echo -echo "=== MEMORY USAGE ===" -free -h | grep -E "(Mem|Swap)" | head -2 - - diff --git a/airootfs/etc/skel/.config/waybar/modules/toggle-record.sh b/airootfs/etc/skel/.config/waybar/modules/toggle-record.sh deleted file mode 100755 index 504a8cb..0000000 --- a/airootfs/etc/skel/.config/waybar/modules/toggle-record.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh - -RECORD_PID_FILE="/tmp/wf-recording.pid" -#AUDIO_SOURCE="$(pactl list short sources | awk '/\.monitor/ && /RUNNING/ { print $2; exit }')" -AUDIO_SOURCE="alsa_output.usb-GeneralPlus_USB_Audio_Device-00.analog-stereo.monitor" - -# Function to stop recording -stop_recording() { - if [ -f "$RECORD_PID_FILE" ]; then - kill -INT "$(cat "$RECORD_PID_FILE")" 2>/dev/null && rm -f "$RECORD_PID_FILE" - fi -} - -# If already recording, stop it -if [ -f "$RECORD_PID_FILE" ] && kill -0 "$(cat "$RECORD_PID_FILE")" 2>/dev/null; then - stop_recording - exit 0 -fi - -# Otherwise, start recording -geometry="$(slurp -d)" -if [ -n "$geometry" ]; then - pkill -USR1 -x record-screend - mkdir -p ~/Videos/Recordings - wf-recorder \ - -f ~/Videos/Recordings/"screen-record-$(date +%Y-%m-%d-%H-%M-%S).mp4" \ - -g "$geometry" \ - --audio \ - --audio-source="$AUDIO_SOURCE" & - echo $! > "$RECORD_PID_FILE" - pkill -USR2 -x record-screend -fi diff --git a/airootfs/etc/skel/.config/waybar/style.css b/airootfs/etc/skel/.config/waybar/style.css old mode 100755 new mode 100644 index 97beef5..f721b13 --- a/airootfs/etc/skel/.config/waybar/style.css +++ b/airootfs/etc/skel/.config/waybar/style.css @@ -1,424 +1,74 @@ +/* SimulationOS - Waybar stylesheet */ * { - font-family: "Fira Sans Semibold", "Font Awesome 6 Free", FontAwesome, Roboto, Helvetica, Arial, sans-serif; - font-size: 14px; /* Slightly smaller font size */ - font-weight: 900; - margin: 0; - padding: 0; - transition-property: background-color; - transition-duration: 0.5s; + font-family: "JetBrainsMono Nerd Font", "Fira Sans", sans-serif; + font-size: 13px; + border: none; + border-radius: 0; + min-height: 0; } -/* Reset all styles */ -* { - border: none; - border-radius: 3px; - min-height: 0; - margin: 0.2em 0.3em 0.2em 0.3em; -} - -/* The whole bar */ -#waybar { - background-color: transparent; - color: #ffffff; - transition-property: background-color; - transition-duration: 0.5s; - border-radius: 0px; - margin: 0px 0px; -} - -window#waybar.hidden { - opacity: 0.2; +window#waybar { + background: rgba(20, 22, 26, 0.85); + color: #e6e6e6; } #workspaces button { - padding: 3px 5px; /* Adjusted padding to reduce height */ - margin: 3px 5px; /* Reduced margin slightly */ - border-radius: 6px; - color: @foreground; - background-color: #111827; - transition: all 0.3s ease-in-out; - font-size: 13px; /* Slightly smaller font size */ + padding: 0 9px; + margin: 3px 2px; + color: #8a8f98; + background: transparent; + border-radius: 6px; } #workspaces button.active { - color: @foreground; - background: #025939; -} - -#workspaces button:hover { - background: #333333; + color: #ffffff; + background: #1793d1; } #workspaces button.urgent { - background-color: #eb4d4b; + color: #ffffff; + background: #c0392b; } -#workspaces { - background-color: #111827; - border-radius: 14px; - padding: 3px 6px; /* Adjusted padding to reduce height */ +#workspaces button:hover { + background: rgba(23, 147, 209, 0.35); } #window { - background-color: #111827; - font-size: 15px; /* Slightly smaller font size */ - font-weight: 800; - color: @foreground; - border-radius: 14px; - padding: 3px 6px; /* Reduced padding */ - margin: 2px; - opacity: 1; + color: #c8ccd4; } -#custom-network_traffic, -#hyprland-window, -#custom-gamemode, -#custom-electricity, -#custom-cpu-temp, -#custom-gpu-temp, -#clock.date, -#clock, -#battery, +#tray, +#pulseaudio, +#network, #cpu, -#custom-cpufreq, #memory, -#disk, #temperature, -#backlight, -#network, -#pulseaudio, -#wireplumber, -#custom-media, -#mode, -#idle_inhibitor, -#mpd, -#bluetooth, -#custom-hyprPicker, -#custom-power-menu, -#custom-spotify, -#custom-weather, -#custom-weather.severe, -#custom-recorder, -#custom-weather.sunnyDay, -#custom-weather.clearNight, -#custom-weather.cloudyFoggyDay, -#custom-weather.cloudyFoggyNight, -#custom-weather.rainyDay, -#custom-weather.rainyNight, -#custom-weather.showyIcyDay, -#custom-weather.snowyIcyNight, -#custom-weather.default { - background-color: #111827; - border-radius: 14px; - padding: 5px; /* Adjusted padding */ -} - - -#custom-recorder { - background-color: #111827; - border-radius: 10px; - padding: 5px; /* Adjusted padding */ - -} - -#custom-screenshot_t { - background-color: #111827; - border-radius: 14px; - padding: 6px; -} - -#custom-weather { - background-color: transparent; - border-radius: 14px; - padding: 6px; -} - -#clock.date { - font-size: 14px; - font-weight: bold; - background-color: #111827; - border-radius: 14px; - padding: 4px 8px; -} - -#custom-gpu-temp, -#custom-cpu-temp { - background-color: #111827; - color: #fb958b; /* match #cpu text color */ - border-radius: 14px; - padding: 6px; /* uniform padding */ - font-weight: bold; - font-size: 14px; - margin: 0 5px; -} - -#custom-electricity { - background-color: #111827; - color: #ebcb8b; /* match #custom-launcher text color */ - border-radius: 14px; /* unify radius to 14px */ - padding: 6px; /* unify padding */ - font-weight: bold; - font-size: 14px; - margin: 0 5px; -} - - -#custom-storage { - background-color: #111827; - color: #ebcb8b; /* Use memory module yellow */ - border-radius: 14px; - padding: 6px; - font-weight: bold; - font-size: 14px; - margin: 0 5px; -} - -#custom-cpufreq { - background-color: #111827; - color: #ffb958; - border-radius: 14px; - padding: 6px; - font-weight: bold; - font-size: 14px; - margin: 0 5px; -} - - - - - -/*()#custom-gpu-temp { - margin: 0 5px; - padding: 0 8px; - border-radius: 8px; - font-weight: bold; - min-width: 80px; -} - - - -#custom-cpu-temp { - margin: 0 5px; - padding: 0 8px; - border-radius: 8px; - font-weight: bold; - min-width: 80px; -} - -*/ - - - - -#custom-spotify { - background-color: #111827; - border-radius: 14px; - padding: 3px 12px; -} - -#tray { - background-color: #111827; - border-radius: 14px; - padding: 6px; /* Adjusted padding */ -} - -#cpu { - color: #fb958b; - background-color: #111827; - padding: 6px; -} - - -#memory { - color: #ebcb8b; - background-color: #111827; - padding: 6px; -} - +#battery, +#clock, #custom-power { - background-color: #111827; - border-radius: 14px; - padding: 6px; -} - -/*#custom-storage { - background-color: #111827; - border-radius: 14px; - padding: 6px; -}*/ - -#custom-launcher { - background-color: #1b242b; - color: #6a92d7; - border-radius: 7.5px; - padding: 3px 6px; /* Adjusted padding */ -} - -#custom-weather.severe { - color: #eb937d; -} - -#custom-weather.sunnyDay { - color: #c2ca76; -} - -#custom-weather.clearNight { - color: #cad3f5; -} - -#custom-weather.cloudyFoggyDay, -#custom-weather.cloudyFoggyNight { - color: #c2ddda; -} - -#custom-weather.rainyDay, -#custom-weather.rainyNight { - color: #5aaca5; -} - -#custom-weather.showyIcyDay, -#custom-weather.snowyIcyNight { - color: #d6e7e5; -} - -#custom-weather.default { - color: #dbd9d8; -} - -/* If workspaces is the leftmost module, omit left margin */ -.modules-left > widget:first-child > #workspaces { - margin-left: 0; -} - -/* If workspaces is the rightmost module, omit right margin */ -.modules-right > widget:last-child > #workspaces { - margin-right: 0; -} - -#pulseaudio { - color: #7d9bba; -} - -#backlight { - color: #8fbcbb; + padding: 0 10px; + margin: 3px 2px; + background: rgba(255, 255, 255, 0.05); + border-radius: 6px; } #clock { - color: #c8d2e0; -} - -#battery { - color: #c0caf5; -} - -#battery.charging, -#battery.full, -#battery.plugged { - color: #26a65b; -} - -@keyframes blink { - to { - background-color: rgba(30, 34, 42, 0.5); - color: #abb2bf; - } -} - -#battery.critical:not(.charging) { - color: #f53c3c; - animation-name: blink; - animation-duration: 0.5s; - animation-timing-function: linear; - animation-iteration-count: infinite; - animation-direction: alternate; -} - -label:focus { - background-color: #000000; + color: #ffffff; + background: rgba(23, 147, 209, 0.28); } -#disk { - background-color: #964b00; -} - -#bluetooth { - color: #707d9d; -} - -#bluetooth.disconnected { - color: #f53c3c; -} - -#network { - color: #b48ead; -} - -#network.disconnected { - color: #f53c3c; -} - -#custom-media { - background-color: #66cc99; - color: #2a5c45; - min-width: 100px; -} - -#custom-media.custom-spotify { - background-color: #66cc99; -} - -#custom-media.custom-vlc { - background-color: #ffa000; -} - -#temperature { - background-color: transparent; -} - -#temperature.critical { - background-color: #eb4d4b; -} - -#tray > .passive { - -gtk-icon-effect: dim; -} - -#tray > .needs-attention { - -gtk-icon-effect: highlight; - background-color: #eb4d4b; -} - -#idle_inhibitor { - background-color: #2d3436; -} - -#idle_inhibitor.activated { - background-color: #ecf0f1; - color: #2d3436; -} - -#language { - background: #00b093; - color: #740864; - padding: 0 0px; - margin: 0 5px; - min-width: 16px; -} - -#keyboard-state { - background: #97e1ad; - color: #000000; - padding: 0 0px; - margin: 0 5px; - min-width: 16px; +#custom-power { + color: #ff7b72; } -#keyboard-state > label { - padding: 0 0px; +#temperature.critical, +#battery.critical { + color: #ffffff; + background: #c0392b; } -#keyboard-state > label.locked { - background: rgba(0, 0, 0, 0.2); +#battery.warning { + color: #f0c674; } - diff --git a/airootfs/etc/ssh/sshd_config.d/10-archiso.conf b/airootfs/etc/ssh/sshd_config.d/10-archiso.conf deleted file mode 100644 index 6ea7b41..0000000 --- a/airootfs/etc/ssh/sshd_config.d/10-archiso.conf +++ /dev/null @@ -1,3 +0,0 @@ -# Allow root login using password authentication -PasswordAuthentication yes -PermitRootLogin yes diff --git a/airootfs/etc/ssh/sshd_config.d/10-simulationos.conf b/airootfs/etc/ssh/sshd_config.d/10-simulationos.conf new file mode 100644 index 0000000..3fd92fc --- /dev/null +++ b/airootfs/etc/ssh/sshd_config.d/10-simulationos.conf @@ -0,0 +1,17 @@ +# SimulationOS. +# +# sshd is installed but NOT enabled by default. SimulationOS is a graphical +# desktop medium, not a headless install medium, so there is no reason to +# expose a network service on a system whose live accounts have no password. +# +# Upstream archiso ships "PermitRootLogin yes" + "PasswordAuthentication yes" +# here for unattended/headless installs. That combination is only safe because +# OpenSSH defaults PermitEmptyPasswords to no. SimulationOS does not rely on +# that: root login over SSH is refused outright. +# +# To use SSH from the live session: +# passwd # give the account a real password +# sudo systemctl start sshd +PermitRootLogin no +PasswordAuthentication yes +PermitEmptyPasswords no diff --git a/airootfs/etc/sudoers.d/10-simulationos-live b/airootfs/etc/sudoers.d/10-simulationos-live new file mode 100644 index 0000000..0527127 --- /dev/null +++ b/airootfs/etc/sudoers.d/10-simulationos-live @@ -0,0 +1,4 @@ +# SimulationOS live medium only. +# Removed from the installed system by simulationos-deloop, which restores a +# password-prompting %wheel rule instead. +%wheel ALL=(ALL:ALL) NOPASSWD: ALL diff --git a/airootfs/etc/sudoers.d/g_wheel b/airootfs/etc/sudoers.d/g_wheel deleted file mode 100644 index 7c499c2..0000000 --- a/airootfs/etc/sudoers.d/g_wheel +++ /dev/null @@ -1 +0,0 @@ -%wheel ALL=(ALL) NOPASSWD: ALL diff --git a/airootfs/etc/systemd/network.conf.d/ipv6-privacy-extensions.conf b/airootfs/etc/systemd/network.conf.d/ipv6-privacy-extensions.conf deleted file mode 100644 index 0e9ceb4..0000000 --- a/airootfs/etc/systemd/network.conf.d/ipv6-privacy-extensions.conf +++ /dev/null @@ -1,2 +0,0 @@ -[Network] -IPv6PrivacyExtensions=yes diff --git a/airootfs/etc/systemd/network/20-ethernet.network b/airootfs/etc/systemd/network/20-ethernet.network deleted file mode 100644 index d3a3271..0000000 --- a/airootfs/etc/systemd/network/20-ethernet.network +++ /dev/null @@ -1,24 +0,0 @@ -[Match] -# Matching with "Type=ether" causes issues with containers because it also matches virtual Ethernet interfaces (veth*). -# See https://bugs.archlinux.org/task/70892 -# Instead match by globbing the network interface name. -Name=en* -Name=eth* - -[Link] -RequiredForOnline=routable - -[Network] -DHCP=yes -MulticastDNS=yes - -# systemd-networkd does not set per-interface-type default route metrics -# https://github.com/systemd/systemd/issues/17698 -# Explicitly set route metric, so that Ethernet is preferred over Wi-Fi and Wi-Fi is preferred over mobile broadband. -# Use values from NetworkManager. From nm_device_get_route_metric_default in -# https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/main/src/core/devices/nm-device.c -[DHCPv4] -RouteMetric=100 - -[IPv6AcceptRA] -RouteMetric=100 diff --git a/airootfs/etc/systemd/network/20-wlan.network b/airootfs/etc/systemd/network/20-wlan.network deleted file mode 100644 index 8b70a95..0000000 --- a/airootfs/etc/systemd/network/20-wlan.network +++ /dev/null @@ -1,20 +0,0 @@ -[Match] -Name=wl* - -[Link] -RequiredForOnline=routable - -[Network] -DHCP=yes -MulticastDNS=yes - -# systemd-networkd does not set per-interface-type default route metrics -# https://github.com/systemd/systemd/issues/17698 -# Explicitly set route metric, so that Ethernet is preferred over Wi-Fi and Wi-Fi is preferred over mobile broadband. -# Use values from NetworkManager. From nm_device_get_route_metric_default in -# https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/main/src/core/devices/nm-device.c -[DHCPv4] -RouteMetric=600 - -[IPv6AcceptRA] -RouteMetric=600 diff --git a/airootfs/etc/systemd/network/20-wwan.network b/airootfs/etc/systemd/network/20-wwan.network deleted file mode 100644 index 6e1c8dd..0000000 --- a/airootfs/etc/systemd/network/20-wwan.network +++ /dev/null @@ -1,19 +0,0 @@ -[Match] -Name=ww* - -[Link] -RequiredForOnline=routable - -[Network] -DHCP=yes - -# systemd-networkd does not set per-interface-type default route metrics -# https://github.com/systemd/systemd/issues/17698 -# Explicitly set route metric, so that Ethernet is preferred over Wi-Fi and Wi-Fi is preferred over mobile broadband. -# Use values from NetworkManager. From nm_device_get_route_metric_default in -# https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/main/src/core/devices/nm-device.c -[DHCPv4] -RouteMetric=700 - -[IPv6AcceptRA] -RouteMetric=700 diff --git a/airootfs/etc/systemd/resolved.conf.d/archiso.conf b/airootfs/etc/systemd/resolved.conf.d/archiso.conf deleted file mode 100644 index 636f3bd..0000000 --- a/airootfs/etc/systemd/resolved.conf.d/archiso.conf +++ /dev/null @@ -1,4 +0,0 @@ -# Default systemd-resolved configuration for archiso - -[Resolve] -MulticastDNS=yes diff --git a/airootfs/etc/systemd/system/dbus-fi.w1.wpa_supplicant1.service b/airootfs/etc/systemd/system/dbus-fi.w1.wpa_supplicant1.service deleted file mode 120000 index 1aff68e..0000000 --- a/airootfs/etc/systemd/system/dbus-fi.w1.wpa_supplicant1.service +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/systemd/system/wpa_supplicant.service \ No newline at end of file diff --git a/airootfs/etc/systemd/system/display-manager.service b/airootfs/etc/systemd/system/display-manager.service new file mode 120000 index 0000000..56f1df2 --- /dev/null +++ b/airootfs/etc/systemd/system/display-manager.service @@ -0,0 +1 @@ +/usr/lib/systemd/system/sddm.service \ No newline at end of file diff --git a/airootfs/etc/systemd/system/multi-user.target.wants/sshd.service b/airootfs/etc/systemd/system/multi-user.target.wants/sshd.service deleted file mode 120000 index d21ebd9..0000000 --- a/airootfs/etc/systemd/system/multi-user.target.wants/sshd.service +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/systemd/system/sshd.service \ No newline at end of file diff --git a/airootfs/etc/systemd/system/multi-user.target.wants/systemd-networkd.service b/airootfs/etc/systemd/system/multi-user.target.wants/systemd-networkd.service deleted file mode 120000 index 4c158e6..0000000 --- a/airootfs/etc/systemd/system/multi-user.target.wants/systemd-networkd.service +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/systemd/system/systemd-networkd.service \ No newline at end of file diff --git a/airootfs/etc/systemd/system/multi-user.target.wants/systemd-resolved.service b/airootfs/etc/systemd/system/multi-user.target.wants/systemd-resolved.service deleted file mode 120000 index 4f6ae34..0000000 --- a/airootfs/etc/systemd/system/multi-user.target.wants/systemd-resolved.service +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/systemd/system/systemd-resolved.service \ No newline at end of file diff --git a/airootfs/etc/systemd/system/multi-user.target.wants/wpa_supplicant.service b/airootfs/etc/systemd/system/multi-user.target.wants/wpa_supplicant.service deleted file mode 120000 index 1aff68e..0000000 --- a/airootfs/etc/systemd/system/multi-user.target.wants/wpa_supplicant.service +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/systemd/system/wpa_supplicant.service \ No newline at end of file diff --git a/airootfs/etc/systemd/system/sockets.target.wants/systemd-networkd.socket b/airootfs/etc/systemd/system/sockets.target.wants/systemd-networkd.socket deleted file mode 120000 index 51942c8..0000000 --- a/airootfs/etc/systemd/system/sockets.target.wants/systemd-networkd.socket +++ /dev/null @@ -1 +0,0 @@ -/usr/lib/systemd/system/systemd-networkd.socket \ No newline at end of file diff --git a/airootfs/etc/systemd/user/default.target.wants/pipewire-pulse.service b/airootfs/etc/systemd/user/default.target.wants/pipewire-pulse.service new file mode 120000 index 0000000..f631f69 --- /dev/null +++ b/airootfs/etc/systemd/user/default.target.wants/pipewire-pulse.service @@ -0,0 +1 @@ +/usr/lib/systemd/user/pipewire-pulse.service \ No newline at end of file diff --git a/airootfs/etc/systemd/user/default.target.wants/pipewire.service b/airootfs/etc/systemd/user/default.target.wants/pipewire.service new file mode 120000 index 0000000..47f171d --- /dev/null +++ b/airootfs/etc/systemd/user/default.target.wants/pipewire.service @@ -0,0 +1 @@ +/usr/lib/systemd/user/pipewire.service \ No newline at end of file diff --git a/airootfs/etc/systemd/user/pipewire-session-manager.service b/airootfs/etc/systemd/user/pipewire-session-manager.service new file mode 120000 index 0000000..a092a62 --- /dev/null +++ b/airootfs/etc/systemd/user/pipewire-session-manager.service @@ -0,0 +1 @@ +/usr/lib/systemd/user/wireplumber.service \ No newline at end of file diff --git a/airootfs/etc/systemd/user/pipewire.service.wants/wireplumber.service b/airootfs/etc/systemd/user/pipewire.service.wants/wireplumber.service new file mode 120000 index 0000000..a092a62 --- /dev/null +++ b/airootfs/etc/systemd/user/pipewire.service.wants/wireplumber.service @@ -0,0 +1 @@ +/usr/lib/systemd/user/wireplumber.service \ No newline at end of file diff --git a/airootfs/etc/systemd/user/sockets.target.wants/pipewire-pulse.socket b/airootfs/etc/systemd/user/sockets.target.wants/pipewire-pulse.socket new file mode 120000 index 0000000..45f6209 --- /dev/null +++ b/airootfs/etc/systemd/user/sockets.target.wants/pipewire-pulse.socket @@ -0,0 +1 @@ +/usr/lib/systemd/user/pipewire-pulse.socket \ No newline at end of file diff --git a/airootfs/etc/systemd/user/sockets.target.wants/pipewire.socket b/airootfs/etc/systemd/user/sockets.target.wants/pipewire.socket new file mode 120000 index 0000000..d871d81 --- /dev/null +++ b/airootfs/etc/systemd/user/sockets.target.wants/pipewire.socket @@ -0,0 +1 @@ +/usr/lib/systemd/user/pipewire.socket \ No newline at end of file diff --git a/airootfs/etc/xdg/reflector/reflector.conf b/airootfs/etc/xdg/reflector/reflector.conf deleted file mode 100644 index 7c830d2..0000000 --- a/airootfs/etc/xdg/reflector/reflector.conf +++ /dev/null @@ -1,8 +0,0 @@ -# Reflector configuration file for the systemd service. - ---save /etc/pacman.d/mirrorlist ---ipv4 ---ipv6 ---protocol https ---latest 20 ---sort rate diff --git a/airootfs/usr/local/bin/Installation_guide b/airootfs/usr/local/bin/Installation_guide deleted file mode 100755 index 58b97b0..0000000 --- a/airootfs/usr/local/bin/Installation_guide +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh -# -# SPDX-License-Identifier: GPL-3.0-or-later - -exec xdg-open 'https://wiki.archlinux.org/title/Installation_guide' diff --git a/airootfs/usr/local/bin/calamares-online.sh b/airootfs/usr/local/bin/calamares-online.sh deleted file mode 100644 index af123d8..0000000 --- a/airootfs/usr/local/bin/calamares-online.sh +++ /dev/null @@ -1,95 +0,0 @@ -#!/bin/bash - -Main() { - # Remove current keyring first, to complete initiate it - sudo rm -rf /etc/pacman.d/gnupg - # We are using this, because archlinux is signing the keyring often with a newly created keyring - # This results into a failed installation for the user. - # Installing archlinux-keyring fails due not being correctly signed - # Mitigate this by installing the latest archlinux-keyring on the ISO, before starting the installation - # The issue could also happen, when the installation does rank the mirrors and then a "faulty" mirror gets used - sudo pacman -Sy --noconfirm archlinux-keyring simulationos-keyring - # Also populate the keys, before starting the Installer, to avoid above issue - sudo pacman-key --init - sudo pacman-key --populate archlinux simulationos - # Also use timedatectl to sync the time with the hardware clock - # There has been a bunch of reports, that the keyring was created in the future - # Syncing appears to fix it - timedatectl set-ntp true - - local progname="$(basename "$0")" - local log="/home/liveuser/simulationos-install.log" - local mode="online" # TODO: keep this line for now - - local _efi_check_dir="/sys/firmware/efi" - local _exitcode=2 # by default use grub - - local SYSTEM="SimulationOS" - local BOOTLOADER="" - if [ -d "${_efi_check_dir}" ]; then - _exitcode=$(yad --width 300 --title "Bootloader" \ - --image=gnome-shutdown \ - --button="Grub:2" \ - --button="Systemd-boot(Default):3" \ - --button="Refind:4" \ - --button="AI SDK / Refind:5" \ - --button="Limine:6" \ - --text "Choose Bootloader/Edition:" ; echo $?) - else - _exitcode=$(yad --width 300 --title "Bootloader" \ - --image=gnome-shutdown \ - --button="Grub:2" \ - --button="Limine:6" \ - --text "Choose Bootloader/Edition:" ; echo $?) - fi - - local ISO_VERSION="$(cat /etc/version-tag)" - echo "USING ISO VERSION: ${ISO_VERSION}" - - if [[ "${_exitcode}" -eq 2 ]]; then - BOOTLOADER="GRUB" - echo "USING GRUB!" - # Remove cachyos calamares packages if they exist (optional) - sudo pacman -Rns --noconfirm cachyos-calamares-qt6-next-systemd cachyos-calamares-qt6-next-grub cachyos-calamares-qt6-next-refind cachyos-calamares-qt6-next-limine || true - # Install your calamares grub package or equivalent - # sudo pacman -Sy simulationos-calamares-grub - elif [[ "${_exitcode}" -eq 3 ]]; then - BOOTLOADER="SYSTEMD-BOOT" - echo "USING SYSTEMD-BOOT!" - sudo pacman -Rns --noconfirm cachyos-calamares-qt6-next-grub cachyos-calamares-qt6-next-refind cachyos-calamares-qt6-next-limine || true - # sudo pacman -Sy simulationos-calamares-systemdboot - elif [[ "${_exitcode}" -eq 4 ]]; then - BOOTLOADER="REFIND" - echo "USING REFIND!" - sudo pacman -Rns --noconfirm cachyos-calamares-qt6-next-grub cachyos-calamares-qt6-next-systemd cachyos-calamares-qt6-next-limine || true - # sudo pacman -Sy simulationos-calamares-refind - elif [[ "${_exitcode}" -eq 5 ]]; then - BOOTLOADER="AI-SDK/Refind" - echo "USING AI SDK and Refind!" - sudo pacman -Rns --noconfirm cachyos-calamares-qt6-next-grub cachyos-calamares-qt6-next-systemd cachyos-calamares-qt6-next-refind cachyos-calamares-qt6-next-limine || true - # sudo pacman -Sy simulationos-calamares-ai - elif [[ "${_exitcode}" -eq 6 ]]; then - BOOTLOADER="Limine" - echo "USING Limine" - sudo pacman -Rns --noconfirm cachyos-calamares-qt6-next-grub cachyos-calamares-qt6-next-systemd cachyos-calamares-qt6-next-refind || true - # sudo pacman -Sy simulationos-calamares-limine - else - exit - fi - - # Get Hardware Informations - inxi -F > $log - - cat <> $log -########## $log by $progname -########## Started (UTC): $(date -u "+%x %X") -########## ISO version: $ISO_VERSION -########## System: $SYSTEM -########## Bootloader: $BOOTLOADER -EOF - - sudo cp "/usr/share/calamares/settings_${mode}.conf" /etc/calamares/settings.conf - sudo -E dbus-launch calamares -D6 >> $log & -} - -Main "$@" diff --git a/airootfs/usr/local/bin/choose-mirror b/airootfs/usr/local/bin/choose-mirror deleted file mode 100755 index 3d26fad..0000000 --- a/airootfs/usr/local/bin/choose-mirror +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash -# -# SPDX-License-Identifier: GPL-3.0-or-later - -get_cmdline() { - local param - for param in $(/etc/pacman.d/mirrorlist < /dev/null ; then - ln -sf /usr/lib/systemd/system/ly.service /etc/systemd/system/display-manager.service -fi -package=sddm -if pacman -Qs $package > /dev/null ; then - ln -sf /usr/lib/systemd/system/sddm.service /etc/systemd/system/display-manager.service -fi -package=gdm -if pacman -Qs $package > /dev/null ; then - ln -sf /usr/lib/systemd/system/gdm.service /etc/systemd/system/display-manager.service -fi -package=lxdm -if pacman -Qs $package > /dev/null ; then - ln -sf /usr/lib/systemd/system/lxdm.service /etc/systemd/system/display-manager.service -fi -package=lightdm -if pacman -Qs $package > /dev/null ; then - ln -sf /usr/lib/systemd/system/lightdm.service /etc/systemd/system/display-manager.service -fi diff --git a/airootfs/usr/local/bin/nvidia-module-loader b/airootfs/usr/local/bin/nvidia-module-loader deleted file mode 100644 index d1558af..0000000 --- a/airootfs/usr/local/bin/nvidia-module-loader +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env bash -# Quick pass if one of the modules is already loaded. -if [[ -e /sys/module/nvidia || -e /sys/module/nouveau ]]; then - exit 0 -fi - -# Using "install" in modprobe seems to result in no dependency resolving for -# modules, so we have to manually set the order in which all modules are loaded -# at once. -load_nvidia_modules() { - local pkgname="$1" - - # Load some basic dependencies of nvidia modules - modprobe video - modprobe drm_ttm_helper - modprobe drm_kms_helper - - for module in nvidia nvidia-modeset nvidia-drm nvidia-uvm; do - modprobe --ignore-install "/usr/share/modules/${pkgname}/${module}.ko.zst" - done -} - -# Load compatible version of NVIDIA modules for current hardware -if chwd --list | awk '{ if($2 == "nouveau" || $2 == "nvidia-dkms-390xx" || $2 == "nvidia-dkms-470xx") f=1 } END {exit (f == 1) ? 0 : 1 }'; then - modprobe nouveau -elif chwd --list | awk '{ if($2 == "nvidia-dkms") f=1 } END {exit (f == 1) ? 0 : 1 }'; then - load_nvidia_modules linux-cachyos-nvidia -elif chwd --list | awk '{ if($2 == "nvidia-open-dkms") f=1 } END {exit (f == 1) ? 0 : 1 }'; then - load_nvidia_modules linux-cachyos-nvidia-open -fi - -# Otherwise, do a fallback to nouveau anyway -if [[ ! -e /sys/module/nouveau && ! -e /sys/module/nvidia ]]; then - modprobe nouveau -fi diff --git a/airootfs/usr/local/bin/prepare-live-desktop.sh b/airootfs/usr/local/bin/prepare-live-desktop.sh deleted file mode 100644 index 2b35714..0000000 --- a/airootfs/usr/local/bin/prepare-live-desktop.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh -# borrowed from manjaro livecd - -xdg=$(xdg-user-dir DESKTOP) -src='/usr/share/applications' - -## We don't need .desktop on desktop, -## actually we should remove .desktop or fix the .desktop as it is running with pkexec, -## and using current calamares config (not even running with script to provide logs). -#if [[ -f /usr/bin/calamares ]]; then -# install -Dm755 $src/calamares.desktop \ -# $xdg/calamares.desktop -#fi - -# workaround for glib trash bug (https://bugzilla.gnome.org/show_bug.cgi?id=748248) -userid=$(id -u $USER) -if [ ! -d "/.Trash-$userid" ]; then - sudo mkdir -p /.Trash-$userid/{expunged,files,info} - sudo chown -R $userid /.Trash-$userid -fi - -# mark launchers trusted for XFCE 4.18 -for f in $(ls $xdg/*desktop); do - gio set -t string $f metadata::xfce-exe-checksum "$(sha256sum $f | awk '{print $1}')" -done; diff --git a/airootfs/usr/local/bin/remove-nvidia b/airootfs/usr/local/bin/remove-nvidia deleted file mode 100644 index 88f79b4..0000000 --- a/airootfs/usr/local/bin/remove-nvidia +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/bash - -_remove_pacman_package() { - local _pkgname="$1" - pacman -Rsnc "$_pkgname" --noconfirm || true -} - -# remove pkgs installed for VMs -_clean_vm_packages() { - - #remove virtualbox - if pacman -Qi virtualbox-guest-utils &> /dev/null; then - systemctl disable vboxservice.service - _remove_pacman_package virtualbox-guest-utils - fi - - if pacman -Qi virtualbox-guest-utils-nox &> /dev/null; then - systemctl disable vboxservice.service - _remove_pacman_package virtualbox-guest-utils-nox - fi - - #remove vmware - if [ -f /etc/xdg/autostart/vmware-user.desktop ]; then - rm /etc/xdg/autostart/vmware-user.desktop - fi - - if pacman -Qi open-vm-tools &> /dev/null; then - systemctl disable vmtoolsd.service - _remove_pacman_package open-vm-tools - fi - - if [ -f /etc/systemd/system/multi-user.target.wants/vmtoolsd.service ]; then - rm /etc/systemd/system/multi-user.target.wants/vmtoolsd.service - fi - - #remove qemu - if pacman -Qi qemu-guest-agent &> /dev/null; then - systemctl disable qemu-guest-agent.service - _remove_pacman_package qemu-guest-agent - fi -} - -_check_not_running_vm="$(systemd-detect-virt | grep -q 'none'; echo $?)" -if [[ "${_check_not_running_vm}" -eq 0 ]]; then - _clean_vm_packages -fi - -# vim:set ft=bash sw=2 sts=2 et: diff --git a/airootfs/usr/local/bin/removeun b/airootfs/usr/local/bin/removeun deleted file mode 100644 index e68b678..0000000 --- a/airootfs/usr/local/bin/removeun +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/bash -#set -e - -_clean_files() { -local _files_to_remove=( - /usr/local/bin/choose-mirror - /usr/local/bin/prepare-live-desktop.sh - /usr/local/bin/removeun-online - /usr/local/share/livecd-sound -) - - local xx - for xx in "${_files_to_remove[@]}"; do rm -rf "$xx" || true; done -} - -_clean_packages() { -local _packages_to_remove=( - gparted - grsync - cachyos-calamares-grub - cachyos-calamares-systemd - cachyos-calamares-refind - cachyos-calamares - cachyos-calamares-config - edk2-shell - boost-libs - doxygen - expect - gpart - tcpdump - arch-install-scripts - squashfs-tools - extra-cmake-modules - cmake - elinks - yaml-cpp - syslinux - clonezilla - memtest86+ - mkinitcpio-archiso -) - - local _check_nvidia_card="$(chwd --is_nvidia_card | grep -q 'NVIDIA card found!'; echo $?)" - if [[ "${_check_nvidia_card}" -ne 0 ]]; then - echo "No NVIDIA card detected. Removing nvidia drivers" - _packages_to_remove+=(linux-cachyos-nvidia-open nvidia-utils egl-wayland) - fi - - local xx - # @ does one by one to avoid errors in the entire process - # taken from Erik Dubois script - for xx in "${_packages_to_remove[@]}"; do pacman -Rsnc "$xx" --noconfirm; done -} - -_clean_packages -_clean_files - -# vim:set ft=bash sw=2 sts=2 et: diff --git a/airootfs/usr/local/bin/removeun-online b/airootfs/usr/local/bin/removeun-online deleted file mode 100644 index a1df016..0000000 --- a/airootfs/usr/local/bin/removeun-online +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/bash - -_clean_packages() { - local _leave_these_packages="base\nbase-devel\ncachyos-keyring\ncachyos-hello\ngrub\nefibootmgr\noctopi\nca-certificates\n" - local _leave_these_basepackages="filesystem\ngcc-libs\nglibc\nglib2\nbash\ncoreutils\nfile\nfindutils\ngawk\ngrep\nprocps-ng\nsed\ntar\ngettext\npciutils\npsmisc\nshadow\nutil-linux\nbzip2\ngzip\nxz\nlicenses\npacman\nsystemd\nsystemd-sysvcompat\niputils\niproute2\n" - local _packages_to_remove=($(comm -23 <(pacman -Qq | sort) <({ pacman -Qqg base-devel; pacman -Qqg cachyos; printf $_leave_these_packages; printf $_leave_these_basepackages; } | sort -u))) - local xx - # @ does one by one to avoid errors in the entire process - # * can be used to treat all packages in one command - for xx in "${_packages_to_remove[@]}"; do pacman -Rs "$xx" --noconfirm; done - - # making sure they are removed -# local _toberemoved_str=$'bash-completion\nxorg-xinit\nxorg-xkill\nxorg-xinput\nxorg-xrandr\nxorg-xrdb\nmkinitcpio-openswap\nalacritty\nkonsole\nkwin-scripts-forceblur\nnetworkmanager-vpnc\nnetworkmanager-qt\nnetworkmanager-openvpn\nwireguard-tools\nopenconnect\nopenvpn\nqt5-xmlpatterns\ndoxygen\ntcpdump\ndmidecode\nkparts\npolkit-qt5\nxorg-server\nxorg-apps\nqt5-tools\nzfs-utils\nlinux-cachyos-zfs\nwget\nvirtualbox-guest-utils\nxf86-video-vesa\nxf86-video-amdgpu\nxf86-video-intel\nnvidia-dkms\nnvidia-utils\nlightdm\nlightdm-gtk-greeter\nlightdm-webkit2-greeter\nbase-devel\nlinux-cachyos-headers\nplasma-browser-integration\nplasma-desktop\nplasma-firewall\nplasma-framework\nplasma-integration\nplasma-nm\nplasma-pa\nplasma-systemmonitor\nplasma-thunderbolt\nplasma-workspace\ndiscover\npackagekit-qt5\nxed\nparole\nristretto\ndolphin\ndolphin-plugins\ncapitaine-cursors\ngtk-engine-murrine\ngnome-themes-extra\nadwaita-icon-theme\nfile-roller\nlibwnck3\nnetwork-manager-applet\ngalculator\ncachy-browser\nkvantum-qt5\nqt5ct\nneofetch\nopen-vm-tools\nxf86-input-vmmouse\nxf86-video-vmware\ncachyos-kde-settings\ncachyos-picom-config\ncachyos-rate-mirrors\ncachyos-kernel-manager\nchwd\noctopi\nreflector-simple\nmeld\nparu\nnordic-theme-git\nlightly-git\ncachyos-nord-kde-theme-git\nchar-white' -# local _toberemoved_packages -# readarray -t _toberemoved_packages <<< "$_toberemoved_str" -# local xxx -# for xxx in "${_toberemoved_packages[@]}"; do pacman -Rs "$xxx" --noconfirm; done - - rm /etc/sddm.conf || true -} - -_pacman_fix() { - -pacman-key --init -pacman-key --populate cachyos -} - -_try_v3() { - /lib/ld-linux-x86-64.so.2 --help | grep "x86-64-v3 (supported, searched)" > /dev/null - - local pacman_conf="/etc/pacman.conf" - local pacman_conf_cachyos="/etc/pacman-more.conf" - local pacman_conf_path_backup="/etc/pacman.conf.bak" - - if [ $? -eq 0 ]; then - echo "x86-64-v3 is supported" - - sed -i 's/Architecture = auto/#Architecture = auto/' $pacman_conf_cachyos - sed -i 's/#//g' $pacman_conf_cachyos - - echo "backup old config" - mv $pacman_conf $pacman_conf_path_backup - - echo "CachyOS -v3 Repo changed" - mv $pacman_conf_cachyos $pacman_conf - - else - echo "x86-64-v3 is not supported" - fi - -} - -_clean_packages -_try_v3 -_pacman_fix diff --git a/airootfs/usr/local/bin/simos-clipboard b/airootfs/usr/local/bin/simos-clipboard new file mode 100755 index 0000000..b818d8a --- /dev/null +++ b/airootfs/usr/local/bin/simos-clipboard @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +# SimulationOS clipboard history picker. +# Requires: cliphist, wofi, wl-clipboard. +set -euo pipefail + +cliphist list \ + | wofi --dmenu --prompt 'Clipboard' --width 720 --lines 12 \ + | cliphist decode \ + | wl-copy diff --git a/airootfs/usr/local/bin/simos-powermenu b/airootfs/usr/local/bin/simos-powermenu new file mode 100755 index 0000000..67f2f7c --- /dev/null +++ b/airootfs/usr/local/bin/simos-powermenu @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +# SimulationOS power menu (wofi based). +set -euo pipefail + +choice="$(printf '%s\n' \ + 'Lock session' \ + 'Log out' \ + 'Reboot' \ + 'Power off' \ + | wofi --dmenu --prompt 'SimulationOS' --lines 5 --width 320)" || exit 0 + +case "$choice" in + 'Lock session') + hyprlock + ;; + 'Log out') hyprctl dispatch exit ;; + 'Reboot') systemctl reboot ;; + 'Power off') systemctl poweroff ;; +esac diff --git a/airootfs/usr/local/bin/simos-screenshot b/airootfs/usr/local/bin/simos-screenshot new file mode 100755 index 0000000..b116627 --- /dev/null +++ b/airootfs/usr/local/bin/simos-screenshot @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +# SimulationOS screenshot helper. +# Requires: grim, slurp, wl-clipboard (all in packages.x86_64). +set -euo pipefail + +mode="${1:-full}" +outdir="${XDG_PICTURES_DIR:-$HOME/Pictures}/Screenshots" +mkdir -p "$outdir" +file="$outdir/simos-$(date +%Y%m%d-%H%M%S).png" + +notify() { + command -v notify-send >/dev/null 2>&1 && notify-send "Screenshot" "$1" || printf '%s\n' "$1" +} + +case "$mode" in + full) + grim "$file" + ;; + area) + geometry="$(slurp)" || exit 1 + grim -g "$geometry" "$file" + ;; + window) + # Ask Hyprland for the focused window's box; fall back to area select. + geometry="" + if command -v hyprctl >/dev/null 2>&1; then + geometry="$(hyprctl activewindow | awk ' + /^[[:space:]]*at:/ { gsub(/,/, " ", $2); ax=$2; ay=$3 } + /^[[:space:]]*size:/ { gsub(/,/, " ", $2); sw=$2; sh=$3 } + END { if (sw != "" && sh != "") printf "%d,%d %dx%d", ax, ay, sw, sh }')" + fi + if [ -z "$geometry" ]; then + geometry="$(slurp)" || exit 1 + fi + grim -g "$geometry" "$file" + ;; + *) + printf 'usage: %s [full|area|window]\n' "${0##*/}" >&2 + exit 2 + ;; +esac + +wl-copy --type image/png < "$file" +notify "Saved to $file and copied to the clipboard" diff --git a/airootfs/usr/local/bin/simulationos-install b/airootfs/usr/local/bin/simulationos-install new file mode 100755 index 0000000..0f31103 --- /dev/null +++ b/airootfs/usr/local/bin/simulationos-install @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +# +# SimulationOS graphical installer launcher. +# +# Starts Calamares against SimulationOS's own configuration tree. That tree +# lives at a SimulationOS-owned path rather than /etc/calamares because the +# cachyos-calamares package already owns /etc/calamares/modules/*.conf and has +# no backup= array, so shipping our own files there would be a hard pacstrap +# file conflict. Calamares' -c/--config flag overrides appDataDir, which +# relocates settings.conf, modules/ AND branding/ into that one directory. +# +set -euo pipefail + +CONFIG_DIR="/usr/share/simulationos/calamares" +LOG="${HOME:-/tmp}/simulationos-install.log" + +die() { printf 'simulationos-install: %s\n' "$1" >&2; exit 1; } + +[ -x /usr/bin/calamares ] || die "Calamares is not installed (/usr/bin/calamares missing)." +[ -r "$CONFIG_DIR/settings.conf" ] || die "SimulationOS installer config missing: $CONFIG_DIR/settings.conf" + +# Re-exec with privileges if we are not root yet. +if [ "$(id -u)" -ne 0 ]; then + if command -v pkexec >/dev/null 2>&1; then + exec pkexec env \ + XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}" \ + WAYLAND_DISPLAY="${WAYLAND_DISPLAY:-}" \ + DISPLAY="${DISPLAY:-}" \ + XDG_CURRENT_DESKTOP="${XDG_CURRENT_DESKTOP:-Hyprland}" \ + QT_QPA_PLATFORM='wayland;xcb' \ + SIMOS_INSTALL_LOG="$LOG" \ + /usr/local/bin/simulationos-install + fi + die "Need root privileges and pkexec is unavailable. Try: sudo -E simulationos-install" +fi + +LOG="${SIMOS_INSTALL_LOG:-$LOG}" + +# Make sure the clock is sane before any signature check happens. +timedatectl set-ntp true 2>/dev/null || true + +{ + printf '===== SimulationOS installation started: %s\n' "$(date -u '+%Y-%m-%dT%H:%M:%SZ')" + printf '===== ISO version: %s\n' "$(sed -n 's/^DISTRIB_RELEASE=//p' /etc/simulationos-release 2>/dev/null || echo unknown)" + command -v inxi >/dev/null 2>&1 && inxi -Fxz 2>/dev/null || true +} >>"$LOG" 2>&1 + +exec calamares -c "$CONFIG_DIR" -D6 >>"$LOG" 2>&1 diff --git a/airootfs/usr/share/applications/simulationos-install.desktop b/airootfs/usr/share/applications/simulationos-install.desktop new file mode 100644 index 0000000..6777efc --- /dev/null +++ b/airootfs/usr/share/applications/simulationos-install.desktop @@ -0,0 +1,12 @@ +[Desktop Entry] +Type=Application +Version=1.0 +Name=Install SimulationOS +GenericName=System Installer +Comment=Install SimulationOS to a disk +Exec=/usr/local/bin/simulationos-install +Icon=simulationos +Terminal=false +Categories=System;Settings; +Keywords=install;installer;calamares;simulationos; +StartupNotify=true diff --git a/airootfs/usr/share/backgrounds/simulationos/simulationos-alpha.png b/airootfs/usr/share/backgrounds/simulationos/simulationos-alpha.png new file mode 100644 index 0000000..15779f7 Binary files /dev/null and b/airootfs/usr/share/backgrounds/simulationos/simulationos-alpha.png differ diff --git a/airootfs/usr/share/pixmaps/simulationos.svg b/airootfs/usr/share/pixmaps/simulationos.svg new file mode 100644 index 0000000..bf9acb5 --- /dev/null +++ b/airootfs/usr/share/pixmaps/simulationos.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + diff --git a/airootfs/usr/share/simulationos/calamares/branding/simulationos/branding.desc b/airootfs/usr/share/simulationos/calamares/branding/simulationos/branding.desc new file mode 100644 index 0000000..839812c --- /dev/null +++ b/airootfs/usr/share/simulationos/calamares/branding/simulationos/branding.desc @@ -0,0 +1,38 @@ +--- +componentName: simulationos + +welcomeStyleCalamares: false +welcomeExpandingLogo: true +windowExpanding: normal +windowSize: 1024px,640px +windowPlacement: center + +sidebar: widget +navigation: widget + +strings: + productName: "SimulationOS" + shortProductName: "SimulationOS" + version: "Alpha" + shortVersion: "Alpha" + versionedName: "SimulationOS Alpha" + shortVersionedName: "SimulationOS Alpha" + bootloaderEntryName: "SimulationOS" + productUrl: "https://github.com/HaiderBassem/SimulationOS" + supportUrl: "https://github.com/HaiderBassem/SimulationOS" + knownIssuesUrl: "https://github.com/HaiderBassem/SimulationOS/issues" + releaseNotesUrl: "https://github.com/HaiderBassem/SimulationOS" + +images: + productLogo: "logo.svg" + productIcon: "icon.svg" + productWelcome: "logo.svg" + +slideshow: "show.qml" +slideshowAPI: 2 + +style: + sidebarBackground: "#14161a" + sidebarText: "#e6e6e6" + sidebarTextSelect: "#1793d1" + sidebarTextHighlight: "#33ccff" diff --git a/airootfs/usr/share/simulationos/calamares/branding/simulationos/icon.svg b/airootfs/usr/share/simulationos/calamares/branding/simulationos/icon.svg new file mode 100644 index 0000000..bf9acb5 --- /dev/null +++ b/airootfs/usr/share/simulationos/calamares/branding/simulationos/icon.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + diff --git a/airootfs/usr/share/simulationos/calamares/branding/simulationos/logo.svg b/airootfs/usr/share/simulationos/calamares/branding/simulationos/logo.svg new file mode 100644 index 0000000..bf9acb5 --- /dev/null +++ b/airootfs/usr/share/simulationos/calamares/branding/simulationos/logo.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + diff --git a/airootfs/usr/share/simulationos/calamares/branding/simulationos/show.qml b/airootfs/usr/share/simulationos/calamares/branding/simulationos/show.qml new file mode 100644 index 0000000..303c81e --- /dev/null +++ b/airootfs/usr/share/simulationos/calamares/branding/simulationos/show.qml @@ -0,0 +1,86 @@ +/* SimulationOS installer slideshow (Calamares slideshow API 2). */ +import QtQuick 2.5 +import calamares.slideshow 1.0 + +Presentation { + id: presentation + + function onActivate() { + presentation.startAutoAdvance(12000); + } + + function onLeave() { + presentation.stopAutoAdvance(); + } + + Slide { + Rectangle { + anchors.fill: parent + color: "#14161a" + Column { + anchors.centerIn: parent + spacing: 18 + Text { + text: "SimulationOS" + color: "#33ccff" + font.pixelSize: 40 + font.bold: true + anchors.horizontalCenter: parent.horizontalCenter + } + Text { + text: "An Arch-based system built around Hyprland." + color: "#e6e6e6" + font.pixelSize: 17 + anchors.horizontalCenter: parent.horizontalCenter + } + } + } + } + + Slide { + Rectangle { + anchors.fill: parent + color: "#14161a" + Column { + anchors.centerIn: parent + spacing: 14 + Text { + text: "Built on the CachyOS kernel" + color: "#33ccff" + font.pixelSize: 30 + anchors.horizontalCenter: parent.horizontalCenter + } + Text { + text: "linux-cachyos, tuned for desktop responsiveness." + color: "#e6e6e6" + font.pixelSize: 16 + anchors.horizontalCenter: parent.horizontalCenter + } + } + } + } + + Slide { + Rectangle { + anchors.fill: parent + color: "#14161a" + Column { + anchors.centerIn: parent + spacing: 14 + Text { + text: "Almost done" + color: "#33ccff" + font.pixelSize: 30 + anchors.horizontalCenter: parent.horizontalCenter + } + Text { + text: "After the reboot, log in at the SimulationOS greeter\nand Hyprland will start automatically." + color: "#e6e6e6" + font.pixelSize: 16 + horizontalAlignment: Text.AlignHCenter + anchors.horizontalCenter: parent.horizontalCenter + } + } + } + } +} diff --git a/airootfs/usr/share/simulationos/calamares/modules/bootloader.conf b/airootfs/usr/share/simulationos/calamares/modules/bootloader.conf new file mode 100644 index 0000000..50530e3 --- /dev/null +++ b/airootfs/usr/share/simulationos/calamares/modules/bootloader.conf @@ -0,0 +1,22 @@ +--- +# SimulationOS installs GRUB on the target. GRUB covers BIOS and UEFI with a +# single code path, which keeps the Alpha's installed-system boot story simple. +# (The ISO itself uses syslinux + systemd-boot; that is a separate concern.) +efiBootLoader: "grub" + +kernel: "/vmlinuz-linux-cachyos" +img: "/initramfs-linux-cachyos.img" +fallback: "/initramfs-linux-cachyos-fallback.img" + +timeout: "5" +bootloaderEntryName: "SimulationOS" +kernelParams: [ "quiet", "loglevel=3" ] + +grubInstall: "grub-install" +grubMkconfig: "grub-mkconfig" +grubCfg: "/boot/grub/grub.cfg" +grubProbe: "grub-probe" +efiBootMgr: "efibootmgr" +efiBootloaderId: "SimulationOS" + +installEFIFallback: true diff --git a/airootfs/usr/share/simulationos/calamares/modules/finished.conf b/airootfs/usr/share/simulationos/calamares/modules/finished.conf new file mode 100644 index 0000000..d117c86 --- /dev/null +++ b/airootfs/usr/share/simulationos/calamares/modules/finished.conf @@ -0,0 +1,4 @@ +--- +restartNowMode: user-unchecked +restartNowCommand: "systemctl -i reboot" +notifyOnFinished: false diff --git a/airootfs/usr/share/simulationos/calamares/modules/fstab.conf b/airootfs/usr/share/simulationos/calamares/modules/fstab.conf new file mode 100644 index 0000000..687b169 --- /dev/null +++ b/airootfs/usr/share/simulationos/calamares/modules/fstab.conf @@ -0,0 +1,14 @@ +--- +mountOptions: + default: defaults,noatime + btrfs: defaults,noatime,compress=zstd + xfs: defaults,noatime + f2fs: defaults,noatime + +ssdExtraMountOptions: + ext4: discard + btrfs: discard=async + xfs: discard + +efiMountOptions: defaults,umask=0077 +crypttabOptions: luks diff --git a/airootfs/usr/share/simulationos/calamares/modules/grubcfg.conf b/airootfs/usr/share/simulationos/calamares/modules/grubcfg.conf new file mode 100644 index 0000000..d1e134e --- /dev/null +++ b/airootfs/usr/share/simulationos/calamares/modules/grubcfg.conf @@ -0,0 +1,9 @@ +--- +overwrite: false +defaults: + GRUB_TIMEOUT: 5 + GRUB_TIMEOUT_STYLE: "menu" + GRUB_DISTRIBUTOR: "SimulationOS" + GRUB_CMDLINE_LINUX_DEFAULT: "quiet loglevel=3" + GRUB_CMDLINE_LINUX: "" + GRUB_ENABLE_CRYPTODISK: false diff --git a/airootfs/usr/share/simulationos/calamares/modules/hwclock.conf b/airootfs/usr/share/simulationos/calamares/modules/hwclock.conf new file mode 100644 index 0000000..9737b45 --- /dev/null +++ b/airootfs/usr/share/simulationos/calamares/modules/hwclock.conf @@ -0,0 +1,2 @@ +--- +# No options; writes the hardware clock according to the chosen timezone. diff --git a/airootfs/usr/share/simulationos/calamares/modules/initcpio.conf b/airootfs/usr/share/simulationos/calamares/modules/initcpio.conf new file mode 100644 index 0000000..31589df --- /dev/null +++ b/airootfs/usr/share/simulationos/calamares/modules/initcpio.conf @@ -0,0 +1,5 @@ +--- +# Runs `mkinitcpio -P` in the target, regenerating +# /boot/initramfs-linux-cachyos.img (and -fallback) from the target's own +# /etc/mkinitcpio.conf. +kernel: "*" diff --git a/airootfs/usr/share/simulationos/calamares/modules/initcpiocfg.conf b/airootfs/usr/share/simulationos/calamares/modules/initcpiocfg.conf new file mode 100644 index 0000000..fcffd2f --- /dev/null +++ b/airootfs/usr/share/simulationos/calamares/modules/initcpiocfg.conf @@ -0,0 +1,3 @@ +--- +# Writes a clean /etc/mkinitcpio.conf for the installed system. +# The archiso drop-in has already been removed by simulationos-deloop. diff --git a/airootfs/usr/share/simulationos/calamares/modules/keyboard.conf b/airootfs/usr/share/simulationos/calamares/modules/keyboard.conf new file mode 100644 index 0000000..ade14d1 --- /dev/null +++ b/airootfs/usr/share/simulationos/calamares/modules/keyboard.conf @@ -0,0 +1,4 @@ +--- +xOrgConfFileName: "/etc/X11/xorg.conf.d/00-keyboard.conf" +convertedKeymapPath: "/usr/share/kbd/keymaps/xkb" +writeEtcDefaultKeyboard: true diff --git a/airootfs/usr/share/simulationos/calamares/modules/locale.conf b/airootfs/usr/share/simulationos/calamares/modules/locale.conf new file mode 100644 index 0000000..c54e660 --- /dev/null +++ b/airootfs/usr/share/simulationos/calamares/modules/locale.conf @@ -0,0 +1,4 @@ +--- +# Offline installer: no GeoIP lookup, the user picks a region on the map. +region: "Europe" +zone: "London" diff --git a/airootfs/usr/share/simulationos/calamares/modules/localecfg.conf b/airootfs/usr/share/simulationos/calamares/modules/localecfg.conf new file mode 100644 index 0000000..eb4956f --- /dev/null +++ b/airootfs/usr/share/simulationos/calamares/modules/localecfg.conf @@ -0,0 +1,3 @@ +--- +# Writes /etc/locale.gen + /etc/locale.conf in the target and runs locale-gen. +localeGenPath: "/etc/locale.gen" diff --git a/airootfs/usr/share/simulationos/calamares/modules/machineid.conf b/airootfs/usr/share/simulationos/calamares/modules/machineid.conf new file mode 100644 index 0000000..cd1e404 --- /dev/null +++ b/airootfs/usr/share/simulationos/calamares/modules/machineid.conf @@ -0,0 +1,5 @@ +--- +systemd: true +dbus: true +dbus-symlink: true +entropy-copy: false diff --git a/airootfs/usr/share/simulationos/calamares/modules/mount.conf b/airootfs/usr/share/simulationos/calamares/modules/mount.conf new file mode 100644 index 0000000..43d64c6 --- /dev/null +++ b/airootfs/usr/share/simulationos/calamares/modules/mount.conf @@ -0,0 +1,37 @@ +--- +extraMounts: + - device: proc + fs: proc + mountPoint: /proc + - device: sys + fs: sysfs + mountPoint: /sys + - device: /dev + mountPoint: /dev + options: [ bind ] + - device: tmpfs + fs: tmpfs + mountPoint: /run + - device: /run/udev + mountPoint: /run/udev + options: [ bind ] + - device: efivarfs + fs: efivarfs + mountPoint: /sys/firmware/efi/efivars + efi: true + +mountOptions: + default: defaults,noatime + btrfs: defaults,noatime,compress=zstd + xfs: defaults,noatime + f2fs: defaults,noatime + +btrfsSubvolumes: + - mountPoint: / + subvolume: /@ + - mountPoint: /home + subvolume: /@home + - mountPoint: /var/log + subvolume: /@log + - mountPoint: /var/cache/pacman/pkg + subvolume: /@pkg diff --git a/airootfs/usr/share/simulationos/calamares/modules/networkcfg.conf b/airootfs/usr/share/simulationos/calamares/modules/networkcfg.conf new file mode 100644 index 0000000..65ddb4f --- /dev/null +++ b/airootfs/usr/share/simulationos/calamares/modules/networkcfg.conf @@ -0,0 +1,4 @@ +--- +# Copies NetworkManager system connections created in the live session into +# the installed system, so a Wi-Fi network joined during installation keeps +# working after the first reboot. diff --git a/airootfs/usr/share/simulationos/calamares/modules/packages.conf b/airootfs/usr/share/simulationos/calamares/modules/packages.conf new file mode 100644 index 0000000..56c81a6 --- /dev/null +++ b/airootfs/usr/share/simulationos/calamares/modules/packages.conf @@ -0,0 +1,17 @@ +--- +backend: pacman + +pacman: + num_retries: 1 + disable_download_timeout: true + needed_only: true + +update_db: false +update_system: false + +operations: + # The installer itself and the live-only partitioning GUI have no place on + # the installed system. try_remove never fails the installation. + - try_remove: + - cachyos-calamares + - gparted diff --git a/airootfs/usr/share/simulationos/calamares/modules/partition.conf b/airootfs/usr/share/simulationos/calamares/modules/partition.conf new file mode 100644 index 0000000..104884e --- /dev/null +++ b/airootfs/usr/share/simulationos/calamares/modules/partition.conf @@ -0,0 +1,24 @@ +--- +efiSystemPartition: "/boot/efi" +efiSystemPartitionSize: 512M +efiSystemPartitionName: EFI + +userSwapChoices: + - none + - small + - suspend + - file + +drawNestedPartitions: false +alwaysShowPartitionLabels: true +allowManualPartitioning: true + +initialPartitioningChoice: none +initialSwapChoice: none + +defaultFileSystemType: "ext4" +availableFileSystemTypes: + - "ext4" + - "btrfs" + - "xfs" + - "f2fs" diff --git a/airootfs/usr/share/simulationos/calamares/modules/removeuser.conf b/airootfs/usr/share/simulationos/calamares/modules/removeuser.conf new file mode 100644 index 0000000..97ffbec --- /dev/null +++ b/airootfs/usr/share/simulationos/calamares/modules/removeuser.conf @@ -0,0 +1,2 @@ +--- +username: liveuser diff --git a/airootfs/usr/share/simulationos/calamares/modules/services-systemd.conf b/airootfs/usr/share/simulationos/calamares/modules/services-systemd.conf new file mode 100644 index 0000000..58948c2 --- /dev/null +++ b/airootfs/usr/share/simulationos/calamares/modules/services-systemd.conf @@ -0,0 +1,30 @@ +--- +units: + - name: "NetworkManager.service" + action: "enable" + mandatory: true + - name: "sddm.service" + action: "enable" + mandatory: true + - name: "bluetooth.service" + action: "enable" + mandatory: false + - name: "systemd-timesyncd.service" + action: "enable" + mandatory: false + - name: "fstrim.timer" + action: "enable" + mandatory: false + # Live-medium services that must not run on an installed system. + - name: "pacman-init.service" + action: "disable" + mandatory: false + - name: "livecd-talk.service" + action: "disable" + mandatory: false + - name: "livecd-alsa-unmuter.service" + action: "disable" + mandatory: false + - name: "vboxservice.service" + action: "disable" + mandatory: false diff --git a/airootfs/usr/share/simulationos/calamares/modules/shellprocess_deloop.conf b/airootfs/usr/share/simulationos/calamares/modules/shellprocess_deloop.conf new file mode 100644 index 0000000..a93224f --- /dev/null +++ b/airootfs/usr/share/simulationos/calamares/modules/shellprocess_deloop.conf @@ -0,0 +1,9 @@ +--- +dontChroot: false +timeout: 600 +verbose: true +script: + - "/usr/share/simulationos/calamares/scripts/simulationos-deloop" + # Runs only after the script above has fully exited, so the script never + # deletes the file it is executing from. + - "rm -rf /usr/share/simulationos" diff --git a/airootfs/usr/share/simulationos/calamares/modules/summary.conf b/airootfs/usr/share/simulationos/calamares/modules/summary.conf new file mode 100644 index 0000000..9e0fe43 --- /dev/null +++ b/airootfs/usr/share/simulationos/calamares/modules/summary.conf @@ -0,0 +1,2 @@ +--- +# Shows the list of actions before they are executed. diff --git a/airootfs/usr/share/simulationos/calamares/modules/umount.conf b/airootfs/usr/share/simulationos/calamares/modules/umount.conf new file mode 100644 index 0000000..eb9ce0a --- /dev/null +++ b/airootfs/usr/share/simulationos/calamares/modules/umount.conf @@ -0,0 +1,2 @@ +--- +srcLog: "/var/log/Calamares.log" diff --git a/airootfs/usr/share/simulationos/calamares/modules/unpackfs.conf b/airootfs/usr/share/simulationos/calamares/modules/unpackfs.conf new file mode 100644 index 0000000..bd74df8 --- /dev/null +++ b/airootfs/usr/share/simulationos/calamares/modules/unpackfs.conf @@ -0,0 +1,9 @@ +--- +# Offline install: copy the live SquashFS onto the target. +# Path comes from archiso: the medium is mounted at /run/archiso/bootmnt and +# the image lives at //airootfs.sfs, with +# install_dir="arch" and arch="x86_64" from profiledef.sh. +unpack: + - source: "/run/archiso/bootmnt/arch/x86_64/airootfs.sfs" + sourcefs: "squashfs" + destination: "" diff --git a/airootfs/usr/share/simulationos/calamares/modules/users.conf b/airootfs/usr/share/simulationos/calamares/modules/users.conf new file mode 100644 index 0000000..753ac90 --- /dev/null +++ b/airootfs/usr/share/simulationos/calamares/modules/users.conf @@ -0,0 +1,40 @@ +--- +defaultGroups: + - name: users + must_exist: true + system: false + - wheel + - audio + - video + - network + - storage + - input + - lp + - scanner + - rfkill + +# The installed system gets a normal login screen; live autologin is not +# carried over. See also sddm.conf.d/20-simulationos-live-autologin.conf, +# which simulationos-deloop deletes from the target. +autologinGroup: autologin +doAutologin: false + +sudoersGroup: wheel +setRootPassword: false +doReusePassword: false + +availableShells: /bin/bash + +passwordRequirements: + nonempty: true + minLength: 6 + +user: + shell: /bin/bash + forbidden_names: + - root + - liveuser + +hostname: + location: EtcFile + writeHostsFile: true diff --git a/airootfs/usr/share/simulationos/calamares/modules/welcome.conf b/airootfs/usr/share/simulationos/calamares/modules/welcome.conf new file mode 100644 index 0000000..563a4d1 --- /dev/null +++ b/airootfs/usr/share/simulationos/calamares/modules/welcome.conf @@ -0,0 +1,19 @@ +--- +showSupportUrl: true +showKnownIssuesUrl: true +showReleaseNotesUrl: false +showDonateUrl: false + +requirements: + requiredStorage: 15 + requiredRam: 1.8 + check: + - storage + - ram + - power + - root + - screen + required: + - storage + - ram + - root diff --git a/airootfs/usr/share/simulationos/calamares/scripts/simulationos-deloop b/airootfs/usr/share/simulationos/calamares/scripts/simulationos-deloop new file mode 100755 index 0000000..5fee79d --- /dev/null +++ b/airootfs/usr/share/simulationos/calamares/scripts/simulationos-deloop @@ -0,0 +1,135 @@ +#!/usr/bin/env bash +# +# simulationos-deloop - turn an unpacked SimulationOS live filesystem into a +# proper installed system. +# +# Runs INSIDE the target chroot, from Calamares' shellprocess@deloop instance, +# after users/removeuser and BEFORE initcpiocfg/initcpio. +# +# Why this exists: the offline installer copies the live SquashFS verbatim, so +# the target initially inherits every live-medium concession - passwordless +# root, NOPASSWD sudo, permissive polkit, SDDM autologin, tty autologin and the +# archiso initramfs hooks. Each of those is removed here. +# +# Deliberately NOT using `set -e`: a missing file must never abort a running +# installation. Every step is individually guarded and logged. +# + +set -u + +log() { printf '[deloop] %s\n' "$*"; } + +drop() { + local path + for path in "$@"; do + if [ -e "$path" ] || [ -L "$path" ]; then + rm -rf -- "$path" && log "removed $path" || log "FAILED to remove $path" + fi + done +} + +log "starting live-configuration removal" + +# ---------------------------------------------------------------- 1. autologin +# SDDM autologin and tty1 autologin are live-medium only. +drop /etc/sddm.conf.d/20-simulationos-live-autologin.conf +drop /etc/systemd/system/getty@tty1.service.d/autologin.conf +rmdir /etc/systemd/system/getty@tty1.service.d 2>/dev/null + +# ------------------------------------------------------- 2. privilege policies +# Replace live NOPASSWD sudo with a normal password-prompting wheel rule. +drop /etc/sudoers.d/10-simulationos-live +drop /etc/sudoers.d/g_wheel +cat > /etc/sudoers.d/10-simulationos-wheel <<'EOSUDO' +## SimulationOS: members of the wheel group may use sudo after authenticating. +%wheel ALL=(ALL:ALL) ALL +EOSUDO +chmod 0440 /etc/sudoers.d/10-simulationos-wheel +chown 0:0 /etc/sudoers.d/10-simulationos-wheel +if command -v visudo >/dev/null 2>&1; then + if visudo -cf /etc/sudoers.d/10-simulationos-wheel >/dev/null 2>&1; then + log "installed password-prompting wheel sudo rule" + else + log "FAILED sudoers validation; removing the new rule to avoid a broken sudo" + rm -f /etc/sudoers.d/10-simulationos-wheel + fi +fi + +# The live polkit rule grants every wheel member every action without a +# password. That must not survive onto a real system. +drop /etc/polkit-1/rules.d/49-simulationos-live-nopasswd.rules + +# ------------------------------------------------------------- 3. root account +# The live medium ships root with an EMPTY password. Calamares is configured +# with setRootPassword:false (sudo-only model), so lock root explicitly. +if passwd --lock root >/dev/null 2>&1; then + log "locked the root account" +else + log "WARNING: could not lock root via passwd; patching /etc/shadow directly" + sed -i 's/^root::/root:!:/' /etc/shadow 2>/dev/null \ + && log "patched /etc/shadow" \ + || log "FAILED to patch /etc/shadow" +fi + +# ------------------------------------------------------------ 4. archiso layer +# This is the load-bearing one: leaving archiso.conf in place makes mkinitcpio +# build an archiso initramfs, and the installed system will not boot without +# the ISO present. +drop /etc/mkinitcpio.conf.d/archiso.conf +rmdir /etc/mkinitcpio.conf.d 2>/dev/null + +drop /etc/systemd/system/livecd-talk.service \ + /etc/systemd/system/livecd-alsa-unmuter.service \ + /etc/systemd/system/multi-user.target.wants/livecd-talk.service \ + /etc/systemd/system/sound.target.wants/livecd-alsa-unmuter.service \ + /etc/systemd/system/pacman-init.service \ + /etc/systemd/system/multi-user.target.wants/pacman-init.service \ + /etc/systemd/system/etc-pacman.d-gnupg.mount \ + /usr/local/bin/livecd-sound \ + /usr/local/share/livecd-sound \ + /root/.automated_script.sh \ + /root/.zlogin + +# archiso masks the GPT auto-generator; an installed system wants it back. +if [ -L /etc/systemd/system-generators/systemd-gpt-auto-generator ]; then + drop /etc/systemd/system-generators/systemd-gpt-auto-generator + rmdir /etc/systemd/system-generators 2>/dev/null +fi + +# Live-only systemd tuning: volatile journal and "never suspend". +drop /etc/systemd/journald.conf.d/volatile-storage.conf +rmdir /etc/systemd/journald.conf.d 2>/dev/null +drop /etc/systemd/logind.conf.d/do-not-suspend.conf +rmdir /etc/systemd/logind.conf.d 2>/dev/null + +# sshd is not enabled on the live medium either, but clear any leftover +# enablement and the upstream archiso drop-in if an older build left one. +drop /etc/systemd/system/multi-user.target.wants/sshd.service \ + /etc/ssh/sshd_config.d/10-archiso.conf + +# ------------------------------------------------------------- 5. the live user +# removeuser has already deleted the account; clear anything left behind. +drop /home/liveuser +for grp in nopasswdlogin autologin; do + if command -v gpasswd >/dev/null 2>&1; then + gpasswd -d liveuser "$grp" >/dev/null 2>&1 + fi +done + +# --------------------------------------------------------------- 6. installer +# The installer must not be offered from an installed system. The +# cachyos-calamares package itself is removed by the `packages` module; +# /usr/share/simulationos is removed by the command after this script. +drop /usr/local/bin/simulationos-install \ + /usr/share/applications/simulationos-install.desktop + +# ------------------------------------------------------------------ 7. banners +# Replace the live console banner with an installed-system one. +cat > /etc/motd <<'EOMOTD' + + SimulationOS + +EOMOTD + +log "finished live-configuration removal" +exit 0 diff --git a/airootfs/usr/share/simulationos/calamares/settings.conf b/airootfs/usr/share/simulationos/calamares/settings.conf new file mode 100644 index 0000000..1d4244b --- /dev/null +++ b/airootfs/usr/share/simulationos/calamares/settings.conf @@ -0,0 +1,64 @@ +--- +# SimulationOS Calamares configuration. +# +# Launched as: calamares -c /usr/share/simulationos/calamares +# The -c flag overrides Calamares' appDataDir, which relocates settings.conf, +# modules/ and branding/ into this directory. This is why SimulationOS does not +# ship anything under /etc/calamares: cachyos-calamares already owns +# /etc/calamares/modules/*.conf and declares no backup= array, so an airootfs +# overlay there would be a hard pacstrap file conflict. +# +# Installation model: OFFLINE. The live SquashFS is unpacked onto the target, +# then live-only configuration is stripped again by the "deloop" shell process. + +modules-search: [ local ] + +instances: +- id: deloop + module: shellprocess + config: shellprocess_deloop.conf + +sequence: +- show: + - welcome + - locale + - keyboard + - partition + - users + - summary +- exec: + - partition + - mount + - unpackfs + - machineid + - fstab + - locale + - keyboard + - localecfg + - users + - networkcfg + - hwclock + - services-systemd + - packages + - removeuser + # deloop MUST run before initcpio: it deletes + # /etc/mkinitcpio.conf.d/archiso.conf, which would otherwise force archiso + # hooks into the installed system's initramfs and make it unbootable + # without the ISO. + - shellprocess@deloop + - initcpiocfg + - initcpio + - grubcfg + - bootloader + - umount +- show: + - finished + +branding: simulationos + +prompt-install: true +dont-chroot: false +oem-setup: false +disable-cancel: false +disable-cancel-during-exec: true +quit-at-end: false diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..1304d0e --- /dev/null +++ b/build.sh @@ -0,0 +1,245 @@ +#!/usr/bin/env bash +# +# build.sh - the single entry point for building SimulationOS. +# +# ./build.sh +# +# This is the ONE build engine. Local developers, CI and the release pipeline +# all call this same script, so a local build and a CI build cannot drift. +# +# It does not itself know how to build an ISO. It works out *where* the build +# can legally happen and then runs scripts/build-iso.sh there: +# +# Arch Linux x86_64 -> run natively +# any other Linux/macOS -> run inside an x86_64 Arch container +# +# SimulationOS targets x86_64. On an arm64 host the container is forced to +# linux/amd64 so we can never silently emit an arm64 ISO. +# +set -euo pipefail + +REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +IMAGE="${SIMOS_BUILDER_IMAGE:-docker.io/archlinux:latest}" +TARGET_ARCH="x86_64" + +CLEAN=0 +NO_CACHE=0 +VERBOSE=0 +FORCE_NATIVE=0 +FORCE_CONTAINER=0 +VALIDATE_ONLY=0 + +red() { printf '\033[31m%s\033[0m\n' "$*" >&2; } +green() { printf '\033[32m%s\033[0m\n' "$*"; } +info() { printf '\033[36m==>\033[0m %s\n' "$*"; } +die() { red "ERROR: $*"; exit 1; } + +usage() { + cat <<'EOF' +usage: ./build.sh [options] + + --clean remove work/ and out/ before building + --no-cache do not reuse the host pacman package cache + --validate run static validation only, then stop + --native force a native build (fails unless Arch x86_64 + root) + --container force a containerised build even on Arch + --verbose verbose build output + -h, --help this message + +Environment: + SIMOS_BUILDER_IMAGE builder image (default docker.io/archlinux:latest) + SIMOS_CONTAINER container runtime (default: a runtime that can mount, + e.g. "docker" or "sudo podman"; rootless podman cannot) + SIMOS_WORK_DIR work directory (default ./work) + SIMOS_OUT_DIR output directory (default ./out) + +Output: + out/simulationos--x86_64.iso (+ .sha256, build-info.json, build.log) +EOF +} + +while [ $# -gt 0 ]; do + case "$1" in + --clean) CLEAN=1 ;; + --no-cache) NO_CACHE=1 ;; + --validate) VALIDATE_ONLY=1 ;; + --native) FORCE_NATIVE=1 ;; + --container) FORCE_CONTAINER=1 ;; + --verbose) VERBOSE=1 ;; + -h|--help) usage; exit 0 ;; + *) die "unknown option: $1 (try --help)" ;; + esac + shift +done + +HOST_OS="$(uname -s)" +HOST_ARCH="$(uname -m)" + +# ----------------------------------------------------------------- validation +# Static validation runs on the host: it is pure bash and needs no pacman, so +# there is no reason to spin up a container to be told the profile is broken. +info "Validating profile" +"$REPO/scripts/validate-profile.sh" || die "profile validation failed" +if [ "$VALIDATE_ONLY" -eq 1 ]; then + green "Validation only (--validate); stopping here." + exit 0 +fi + +# ------------------------------------------------------------- where to build +is_native_capable() { + [ "$HOST_OS" = "Linux" ] || return 1 + [ "$HOST_ARCH" = "$TARGET_ARCH" ] || return 1 + command -v mkarchiso >/dev/null 2>&1 || return 1 + return 0 +} + +MODE="container" +if [ "$FORCE_NATIVE" -eq 1 ]; then + MODE="native" +elif [ "$FORCE_CONTAINER" -eq 1 ]; then + MODE="container" +elif is_native_capable; then + MODE="native" +fi + +printf '\n' +info "Host: $HOST_OS $HOST_ARCH" +info "Target: linux $TARGET_ARCH" +info "Builder: $MODE" +printf '\n' + +# ---------------------------------------------------------------- clean first +if [ "$CLEAN" -eq 1 ]; then + "$REPO/scripts/clean-build.sh" +fi + +# -------------------------------------------------------------- native build +if [ "$MODE" = "native" ]; then + is_native_capable || die "--native requested but this host cannot build natively + (need Linux $TARGET_ARCH with mkarchiso installed; this is $HOST_OS $HOST_ARCH)." + [ "$(id -u)" -eq 0 ] || die "a native build must run as root. Try: sudo ./build.sh" + exec "$REPO/scripts/build-iso.sh" +fi + +# ----------------------------------------------------------- container build +# pacstrap bind-mounts /dev inside the chroot, which needs real CAP_SYS_ADMIN +# on the host. A ROOTLESS podman cannot provide that even with --privileged: +# mount: .../airootfs/dev: permission denied +# ==> ERROR: failed to setup chroot +# GitHub's ubuntu-latest ships rootless podman alongside a rootful docker, so +# the runtime is chosen by capability, not by name order. +RUNTIME=() +if [ -n "${SIMOS_CONTAINER:-}" ]; then + # Explicit override: honour it verbatim, including "sudo podman". + read -r -a RUNTIME <<<"$SIMOS_CONTAINER" +else + if command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1; then + RUNTIME=(docker) + elif command -v podman >/dev/null 2>&1; then + if [ "$(podman info --format '{{.Host.Security.Rootless}}' 2>/dev/null)" = "true" ]; then + if [ "$(id -u)" -eq 0 ]; then + RUNTIME=(podman) + elif sudo -n true 2>/dev/null; then + info "podman is rootless; using 'sudo podman' so pacstrap can mount /dev" + RUNTIME=(sudo podman) + else + die "podman here is ROOTLESS and docker is unavailable. + pacstrap must bind-mount /dev inside the chroot, which rootless + containers cannot do even with --privileged. Either: + - install/start docker, or + - run: sudo ./build.sh, or + - set SIMOS_CONTAINER='sudo podman'" + fi + else + RUNTIME=(podman) + fi + fi +fi + +[ "${#RUNTIME[@]}" -gt 0 ] || die "no usable container runtime found. Install docker or podman, + or build on an Arch Linux $TARGET_ARCH host and use --native." + +"${RUNTIME[@]}" info >/dev/null 2>&1 \ + || die "${RUNTIME[*]} is installed but not responding. Start it and retry." + +EMULATED=0 +if [ "$HOST_ARCH" != "$TARGET_ARCH" ]; then + EMULATED=1 + red "NOTE: host is $HOST_ARCH but the target is $TARGET_ARCH." + red " The builder runs under emulation, which is CORRECT but SLOW." + red " A native x86_64 machine will be dramatically faster." + printf '\n' +fi + +CACHE_ARGS=() +if [ "$NO_CACHE" -eq 0 ]; then + CACHE_DIR="$REPO/.cache/pacman" + mkdir -p "$CACHE_DIR" + CACHE_ARGS=(-v "$CACHE_DIR:/var/cache/pacman/pkg") + info "Reusing package cache at .cache/pacman (use --no-cache to disable)" +fi + +# mkarchiso needs loop devices, mount and squashfs; those require elevated +# container privileges. This is the same model CachyOS uses in its CI. +info "Starting ${RUNTIME[*]} builder ($IMAGE, platform linux/amd64)" +exec "${RUNTIME[@]}" run --rm -i \ + --platform linux/amd64 \ + --privileged \ + -v "$REPO:/simulationos" \ + "${CACHE_ARGS[@]}" \ + -w /simulationos \ + -e "SIMOS_VERBOSE=$VERBOSE" \ + -e "SIMOS_EMULATED=$EMULATED" \ + -e "SIMOS_WORK_DIR=/var/tmp/simulationos-work" \ + -e "SIMOS_OUT_DIR=/simulationos/out" \ + "$IMAGE" \ + bash -euo pipefail -c ' + printf "\033[36m==>\033[0m builder arch: $(uname -m)\n" + [ "$(uname -m)" = "x86_64" ] || { echo "ERROR: builder is not x86_64"; exit 1; } + + # pacman >=7 sandboxes downloads with seccomp and an unprivileged + # user. Under qemu-user emulation that syscall filter fails outright: + # error restricting syscalls via seccomp: 22! (EINVAL) + # It must be disabled BEFORE the first pacman call, and only for this + # throwaway builder. Signature verification is untouched and the + # committed pacman.conf is never modified - validate-profile.sh fails + # if DisableSandbox ever appears in a committed config. + if [ "${SIMOS_EMULATED:-0}" = "1" ]; then + printf "\033[33m==>\033[0m Emulated builder: disabling the pacman sandbox (this container only)\n" + grep -q "^DisableSandbox" /etc/pacman.conf \ + || sed -i "0,/^\[options\]/s//[options]\nDisableSandbox/" /etc/pacman.conf + SIMOS_PACMAN_CONF=/tmp/pacman.emulated.conf + sed "0,/^\[options\]/s//[options]\nDisableSandbox/" \ + /simulationos/pacman.conf > "$SIMOS_PACMAN_CONF" + export SIMOS_PACMAN_CONF + # Belt and braces: the conf setting is not always honoured for + # pacman calls made here, so pass the flag explicitly too. + PACFLAGS="--disable-sandbox" + fi + PACFLAGS="${PACFLAGS:-}" + + printf "\033[36m==>\033[0m Refreshing keyring and installing archiso\n" + pacman $PACFLAGS -Sy --noconfirm --needed archlinux-keyring >/dev/null + pacman $PACFLAGS -S --noconfirm --needed archiso git >/dev/null + + # Without this, git refuses to read the bind-mounted repo ("dubious + # ownership") and build-info.json records git_commit: unknown, which + # defeats the point of build provenance. + git config --global --add safe.directory /simulationos + + printf "\033[36m==>\033[0m Trusting the CachyOS signing key\n" + pacman-key --init >/dev/null 2>&1 || true + pacman-key --populate archlinux >/dev/null 2>&1 || true + pacman-key --recv-keys F3B607488DB35A47 --keyserver keyserver.ubuntu.com >/dev/null 2>&1 \ + || { echo "ERROR: could not fetch the CachyOS signing key"; exit 1; } + pacman-key --lsign-key F3B607488DB35A47 >/dev/null 2>&1 + + # Install the keyring through the profile pacman.conf so there is no + # hardcoded package-version URL to go stale. + pacman $PACFLAGS -Sy --noconfirm --needed --config "${SIMOS_PACMAN_CONF:-/simulationos/pacman.conf}" \ + cachyos-keyring cachyos-mirrorlist >/dev/null \ + || { echo "ERROR: could not install cachyos-keyring"; exit 1; } + pacman-key --populate cachyos >/dev/null 2>&1 || true + + exec /simulationos/scripts/build-iso.sh + ' diff --git a/docs/adr/0001-archiso-baseline.md b/docs/adr/0001-archiso-baseline.md new file mode 100644 index 0000000..1d6bc51 --- /dev/null +++ b/docs/adr/0001-archiso-baseline.md @@ -0,0 +1,24 @@ +# ADR 0001 - archiso is the architectural baseline + +**Status:** accepted · 2026-09-28 + +## Context +The repository began as a copy of Arch's `releng` profile and had drifted: +six removed bootmode names, a variable (`iso_icon`) mkarchiso never reads, and +a custom mkinitcpio preset upstream had deleted. + +## Decision +Track current archiso exactly. Do not fork it, do not reimplement it, do not +keep deprecated spellings because an old profile used them. + +## Alternatives +- **Fork archiso** — rejected: permanent maintenance cost for no benefit yet. +- **Copy the CachyOS ISO profile** — rejected, see ADR 0003. + +## Consequences +We inherit archiso's improvements for free, but must re-read its CHANGELOG at +each upgrade. `validate-profile.sh` fails on deprecated bootmodes and on +variables mkarchiso does not consume, so drift is caught mechanically. + +## Sources +`docs/research/sources.md` § archiso. diff --git a/docs/adr/0002-kernel-linux-cachyos.md b/docs/adr/0002-kernel-linux-cachyos.md new file mode 100644 index 0000000..deee86b --- /dev/null +++ b/docs/adr/0002-kernel-linux-cachyos.md @@ -0,0 +1,27 @@ +# ADR 0002 - Ship linux-cachyos + +**Status:** accepted · 2026-09-28 + +## Context +SimulationOS' stated identity includes the CachyOS kernel. The repository +already listed `linux-cachyos` but no boot path referenced its actual files. + +## Decision +Ship `linux-cachyos` as the only kernel, and derive every filename from its +`pkgbase`: `vmlinuz-linux-cachyos`, `initramfs-linux-cachyos.img`, preset +`linux-cachyos.preset`. Delete the hand-written preset. + +## Alternatives +- **Stock `linux`** — simpler, but discards a defining project property. +- **Keep a custom preset** — rejected: presets are keyed to `pkgbase`, so a + `linux.preset` is orphaned; upstream removed theirs for the same reason. + +## Consequences +We depend on the CachyOS repository for the kernel, so a CachyOS outage blocks +builds. No fallback/LTS kernel yet — see ADR 0012. +The validator derives expected filenames from `packages.x86_64` and fails on +any drift, which is how the original three-way mismatch would have been caught. + +## Sources +`linux-cachyos/PKGBUILD:177,612,615`. Resolution verified in an x86_64 +container: `cachyos/linux-cachyos-7.2.7-1`. diff --git a/docs/adr/0003-cachyos-as-supplier.md b/docs/adr/0003-cachyos-as-supplier.md new file mode 100644 index 0000000..88e4ac0 --- /dev/null +++ b/docs/adr/0003-cachyos-as-supplier.md @@ -0,0 +1,27 @@ +# ADR 0003 - CachyOS is a component supplier, not a template + +**Status:** accepted · 2026-09-28 + +## Context +CachyOS solves several problems we also have. The temptation is to copy its +ISO profile and repo ordering wholesale. + +## Decision +Depend on CachyOS for what is genuinely exclusive to it and nothing else: +`linux-cachyos`, `cachyos-calamares`, `ckbcomp`, `mkinitcpio-openswap`, +`cachyos-keyring`, `cachyos-mirrorlist`. List Arch repositories **before** +`[cachyos]` so a package present in both comes from Arch. + +## Alternatives +- **CachyOS ordering ([cachyos] first)** — rejected: pulls the whole optimised + package set and makes our dependency surface unpredictable. +- **Vendor their files** — rejected: copying code we do not understand is how + the inherited `chwd`-dependent dead scripts got here in the first place. + +## Consequences +Predictable dependency graph, verified: of 577 resolved packages, exactly 6 +come from `[cachyos]`. We forgo CachyOS' x86-64-v3/v4 optimised builds; if we +later want them, that is a deliberate, separately measured decision. + +## Sources +`docs/research/sources.md` § CachyOS; container resolution run 2026-09-28. diff --git a/docs/adr/0004-hyprland-desktop.md b/docs/adr/0004-hyprland-desktop.md new file mode 100644 index 0000000..fc5b518 --- /dev/null +++ b/docs/adr/0004-hyprland-desktop.md @@ -0,0 +1,26 @@ +# ADR 0004 - Hyprland from stable repositories + +**Status:** accepted · 2026-09-28 + +## Context +Hyprland is the SimulationOS desktop. Its ecosystem (portal, polkit agent, +lock, paper) has coupled ABI expectations across releases. + +## Decision +Use only official Arch repository packages. No `-git`, no AUR in the base OS. +One component per job: `hyprland`, `hyprpaper`, `hyprlock`, +`hyprpolkitagent`, `waybar`, `wofi`, `kitty`, `thunar`, `mako`. + +## Alternatives +- **`hyprland-git`** — rejected: upstream warns about interlocking ABI + dependencies; a distribution baseline cannot chase that. +- **Ship several launchers/terminals** — rejected: more to test, no user benefit. + +## Consequences +We lag upstream Hyprland slightly. In exchange the desktop is reproducible and +every referenced binary is guaranteed present — enforced by the validator, +which fails if `hyprland.conf` launches anything not in `packages.x86_64`. + +## Sources +`docs/research/sources.md` § Hyprland. Note `swww` and `rofi-wayland` are not +in the Arch repositories, which is why `hyprpaper` and `wofi` were chosen. diff --git a/docs/adr/0005-sddm-display-manager.md b/docs/adr/0005-sddm-display-manager.md new file mode 100644 index 0000000..4287972 --- /dev/null +++ b/docs/adr/0005-sddm-display-manager.md @@ -0,0 +1,26 @@ +# ADR 0005 - SDDM with an X11 greeter launching a Wayland session + +**Status:** provisional · 2026-09-28 + +## Context +We need autologin on the live medium and a normal greeter on the installed +system. SDDM's Wayland greeter needs a compositor. + +## Decision +SDDM with its default `DisplayServer=x11` greeter, launching +`hyprland.desktop` from `/usr/share/wayland-sessions`. Theme `maldives`. + +## Alternatives +- **SDDM Wayland greeter** — needs `weston` (`CompositorCommand=weston + --shell=kiosk`); an extra compositor purely for the login screen. +- **greetd + tuigreet** — lighter, but a text greeter undercuts "polished". +- **No display manager** — rejected: the installed system needs a real login. + +## Consequences +Xorg is pulled in as a hard dependency of `sddm` regardless. Revisit when +SDDM's Wayland greeter no longer requires a separate compositor — hence +*provisional*. The previous config specified theme `breeze`, which needs +Plasma and was not installed; only `elarun`, `maldives`, `maya` ship with SDDM. + +## Sources +`docs/research/sources.md` § Display manager. diff --git a/docs/adr/0006-networkmanager.md b/docs/adr/0006-networkmanager.md new file mode 100644 index 0000000..7d39bc7 --- /dev/null +++ b/docs/adr/0006-networkmanager.md @@ -0,0 +1,23 @@ +# ADR 0006 - NetworkManager is the only network stack + +**Status:** accepted · 2026-09-28 + +## Context +Upstream releng uses systemd-networkd + iwd + systemd-resolved, suited to a +headless install medium. The repository had inherited that while also enabling +NetworkManager. + +## Decision +NetworkManager alone. `wpa_supplicant` stays installed but is D-Bus-activated, +not statically enabled. systemd-resolved is dropped, so NetworkManager owns +`/etc/resolv.conf`. + +## Alternatives +- **networkd + resolved** — better for servers, no desktop GUI story. +- **NetworkManager + systemd-resolved** — viable and adds DNS caching/DNSSEC, + but is a second moving part; revisit once the base is proven. + +## Consequences +One component owns connectivity. Calamares' `networkcfg` migrates live +connections into the installed system, so Wi-Fi joined during installation +keeps working. The validator fails if both stacks are ever enabled at once. diff --git a/docs/adr/0007-pipewire-audio.md b/docs/adr/0007-pipewire-audio.md new file mode 100644 index 0000000..6901da2 --- /dev/null +++ b/docs/adr/0007-pipewire-audio.md @@ -0,0 +1,27 @@ +# ADR 0007 - PipeWire + WirePlumber, enabled explicitly + +**Status:** accepted · 2026-09-28 + +## Context +The profile shipped no audio stack. Arch's pipewire packages ship user units +but **no** `.wants` symlinks, and Arch does not run `systemctl preset` at +package-install time. + +## Decision +PipeWire with `pipewire-pulse`, `pipewire-alsa`, `pipewire-jack` and +WirePlumber, enabled by explicit symlinks under `/etc/systemd/user/` derived +from each unit's real `[Install]` section. + +## Alternatives +- **Rely on presets** — rejected: not applied on Arch at install time; audio + would silently not start. +- **PulseAudio** — rejected: PipeWire is the current desktop default and gives + JACK and screen-share audio in one stack. + +## Consequences +Enablement is visible in the repository rather than implicit. If upstream +changes an `[Install]` section, our symlinks go stale — the validator flags +dangling systemd symlinks. + +## Sources +Unit files extracted from the actual packages; see `docs/research/sources.md` § Audio. diff --git a/docs/adr/0008-calamares-offline.md b/docs/adr/0008-calamares-offline.md new file mode 100644 index 0000000..54e6048 --- /dev/null +++ b/docs/adr/0008-calamares-offline.md @@ -0,0 +1,32 @@ +# ADR 0008 - Calamares, offline install, SimulationOS-owned config directory + +**Status:** accepted · 2026-09-28 + +## Context +Calamares is not in the Arch repositories; `cachyos-calamares` provides it. +That package owns ~60 files under `/etc/calamares/modules/` and declares no +`backup` array. archiso copies `airootfs/` **before** pacstrap, so shipping +our configs at those paths is a hard file conflict. + +## Decision +Ship a self-contained tree at `/usr/share/simulationos/calamares` and launch +`calamares -c /usr/share/simulationos/calamares`. Install offline via +`unpackfs`, then strip live-only configuration with `simulationos-deloop`. + +## Alternatives +- **Files in `/etc/calamares`** — breaks the build. +- **Suffixed module configs + `instances:`** — works, but we override nearly + every module, so it means ~20 oddly named files sitting beside CachyOS'. +- **Fork Calamares** — rejected, large permanent cost. +- **Online `pacstrap` install** — more flexible, needs network and is slower; + offline matches "the live desktop is what you get". + +## Consequences +Verified in Calamares source that `-c` relocates settings, module configs +**and** branding, so CachyOS defaults cannot leak in. The trade-off is that +`unpackfs` copies the live filesystem verbatim, which makes `deloop` a +correctness-critical component — including locking root, which the live medium +leaves passwordless. `deloop` must run before `initcpio`. + +## Sources +`docs/research/sources.md` § Calamares. diff --git a/docs/adr/0009-grub-for-installed-system.md b/docs/adr/0009-grub-for-installed-system.md new file mode 100644 index 0000000..1287126 --- /dev/null +++ b/docs/adr/0009-grub-for-installed-system.md @@ -0,0 +1,23 @@ +# ADR 0009 - GRUB on the installed system + +**Status:** provisional · 2026-09-28 + +## Context +The ISO boots via syslinux (BIOS) and systemd-boot (UEFI). The installed +system's bootloader is a separate decision; the inherited installer script +offered five choices, none of them wired up. + +## Decision +One bootloader for the installed system: GRUB, via Calamares' `bootloader` +module with `GRUB_DISTRIBUTOR="SimulationOS"`. + +## Alternatives +- **systemd-boot** — simpler and faster, but UEFI-only and needs the kernel on + the ESP, which complicates sizing. +- **Offer a choice (GRUB/systemd-boot/rEFInd/Limine)** — rejected for Alpha: + each option multiplies the install-test matrix. + +## Consequences +One code path covering BIOS and UEFI. Slower boot than systemd-boot. Marked +*provisional*: once the install test is automated, systemd-boot becomes cheap +to evaluate on measured boot-time evidence. diff --git a/docs/adr/0010-skel-as-config-source.md b/docs/adr/0010-skel-as-config-source.md new file mode 100644 index 0000000..76cfb68 --- /dev/null +++ b/docs/adr/0010-skel-as-config-source.md @@ -0,0 +1,29 @@ +# ADR 0010 - /etc/skel is the single source of desktop configuration + +**Status:** accepted · 2026-09-28 + +## Context +The live user's dotfiles and the installed user's dotfiles must not diverge. +An earlier reading suggested archiso never applies `/etc/skel`; reading +`mkarchiso` disproved that. + +## Decision +Keep desktop configuration only in `airootfs/etc/skel/.config/`. archiso's +`_make_customize_airootfs` materialises `/home/liveuser` from it with correct +ownership, and Calamares' `users` module copies the same skel for the +installed user. + +## Alternatives +- **Ship `airootfs/home/liveuser/`** — duplicates every dotfile and needs + manual recursive `file_permissions`. +- **A first-login provisioning script** — more machinery, more to fail. + +## Consequences +Live and installed desktops are identical by construction. Users who edit +their dotfiles are never overwritten, because skel is only copied at account +creation. The cost: changing a default does not reach existing users — a +migration story is still **open** if we later package the config (see the +"packaged config" item in `docs/research/sources.md`). + +## Sources +`mkarchiso:_make_customize_airootfs()`, invoked at line 1852 (after pacstrap). diff --git a/docs/adr/0011-filesystem-ext4-default.md b/docs/adr/0011-filesystem-ext4-default.md new file mode 100644 index 0000000..2579cf3 --- /dev/null +++ b/docs/adr/0011-filesystem-ext4-default.md @@ -0,0 +1,23 @@ +# ADR 0011 - ext4 is the default filesystem + +**Status:** provisional · 2026-09-28 + +## Context +Btrfs is fashionable for snapshot-based rollback. Snapshots alone are not a +rollback system. + +## Decision +Default to ext4. Offer Btrfs, XFS and f2fs in the installer, with Btrfs +subvolumes (`@`, `@home`, `@log`, `@pkg`) pre-configured for anyone choosing it. +Do **not** advertise rollback. + +## Alternatives +- **Btrfs by default with snapshots** — rejected for now: a credible rollback + promise needs snapshot-on-transaction, boot integration, kernel/initramfs + handling, pruning and tested recovery. We cannot maintain or test that yet, + and a half-working rollback is worse than none. + +## Consequences +Simple, predictable default. Revisit when we can own the whole lifecycle *and* +test it automatically. Promoting this to Btrfs-by-default requires an +automated rollback test in CI first. diff --git a/docs/adr/0012-no-custom-kernel-yet.md b/docs/adr/0012-no-custom-kernel-yet.md new file mode 100644 index 0000000..9c27d2b --- /dev/null +++ b/docs/adr/0012-no-custom-kernel-yet.md @@ -0,0 +1,20 @@ +# ADR 0012 - No SimulationOS kernel fork + +**Status:** accepted · 2026-09-28 + +## Context +Distributions often start patching kernels early. We already consume a tuned +kernel via `linux-cachyos`. + +## Decision +No SimulationOS kernel. Consume `linux-cachyos` as a package. + +## Before this may be revisited, all of these are required +a measured problem · a benchmark demonstrating the gain · a maintenance owner · +a security-update plan · kernel CI · a tested fallback kernel. + +## Consequences +Zero kernel maintenance burden. **Gap:** there is currently no fallback kernel, +so a bad `linux-cachyos` update has no in-place escape hatch other than the +live ISO. Adding `linux-lts` as a recovery kernel is the next step here and is +tracked as a Phase 3 item. diff --git a/docs/adr/0013-profiles-as-metapackages.md b/docs/adr/0013-profiles-as-metapackages.md new file mode 100644 index 0000000..18b3417 --- /dev/null +++ b/docs/adr/0013-profiles-as-metapackages.md @@ -0,0 +1,29 @@ +# ADR 0013 - Capability profiles as meta-packages + +**Status:** open · 2026-09-28 + +## Context +SimulationOS targets programming, networking and gaming without installing all +three everywhere. The base must stay small. + +## Proposed decision +Express profiles as SimulationOS meta-packages +(`simulationos-dev-meta`, `-network-meta`, `-gaming-meta`, `-gaming-apps`), +selected in the installer and installable later, rather than as a shell script +that installs a list of packages. + +## Why this is still open +Meta-packages need a SimulationOS **repository**, which needs signing keys, +a keyring package, mirrors and package CI. Until that exists, the installer +can only select from Arch/CachyOS packages directly. + +## Evidence needed first +- repository hosting and signing-key custody +- whether `Group` or a meta-package gives better uninstall semantics +- the GPU/32-bit provider-ordering problem for gaming (ADR pending): a naive + Steam dependency pull can select the wrong vendor's 32-bit Vulkan driver + +## Interim +Profiles are **not** implemented. The base desktop is installed as-is. Doing +this badly (a shell script downloading dozens of packages post-install) would +be worse than waiting. diff --git a/docs/adr/0014-nftables-firewall.md b/docs/adr/0014-nftables-firewall.md new file mode 100644 index 0000000..7cb1d6e --- /dev/null +++ b/docs/adr/0014-nftables-firewall.md @@ -0,0 +1,30 @@ +# ADR 0014 - Default nftables policy + +**Status:** open · 2026-09-28 + +## Context +SimulationOS currently ships no firewall. Its exposure is presently low: the +live medium enables no listening network service (sshd is installed but +disabled, unlike upstream archiso). + +## Proposed decision +A minimal stateful nftables policy: drop inbound by default; accept +established/related and loopback; allow DHCP/DHCPv6 and essential ICMP/ICMPv6; +leave outbound open. + +## Why this is still open +Needs verification against real desktop traffic before being enabled by +default: mDNS/Avahi for printer and cast discovery, KDE Connect, Steam +in-home streaming and local multiplayer, and WireGuard/OpenVPN interfaces all +have inbound expectations. Shipping a policy that silently breaks LAN gaming +is worse than shipping none. + +## Evidence needed first +- an inbound-traffic inventory for a normal desktop session +- confirmation that ICMPv6 rules do not break IPv6 SLAAC/PMTUD +- a documented way for a network engineer to extend the ruleset + +## Interim +No firewall is enabled, and the attack surface is kept small instead by not +enabling listening services. This is recorded as a **known gap**, not as a +decision that a firewall is unnecessary. diff --git a/docs/adr/0015-single-build-engine.md b/docs/adr/0015-single-build-engine.md new file mode 100644 index 0000000..614485c --- /dev/null +++ b/docs/adr/0015-single-build-engine.md @@ -0,0 +1,26 @@ +# ADR 0015 - One build engine: ./build.sh + +**Status:** accepted · 2026-09-28 + +## Context +The classic distribution failure is a local build that differs from CI, which +differs from the release build. + +## Decision +`./build.sh` is the only entry point, for developers, CI and releases. It +chooses *where* to build (native Arch x86_64, or an x86_64 Arch container) and +then runs the same `scripts/build-iso.sh` either way. CI must never implement +its own build procedure. + +## Alternatives +- **A separate CI workflow that calls mkarchiso directly** — rejected; this is + exactly the drift we are avoiding. + +## Consequences +An arm64 host builds through emulation rather than silently producing an arm64 +ISO. One environment-specific concession was needed and is scoped tightly: +pacman's seccomp sandbox fails with `EINVAL` under qemu-user emulation, so the +**container** patches a throwaway copy of `pacman.conf` with `DisableSandbox`. +The committed `pacman.conf` never sets it, signature verification is never +disabled, and `validate-profile.sh` fails if `DisableSandbox` or +`SigLevel = Never` ever appears in a committed config. diff --git a/docs/adr/README.md b/docs/adr/README.md new file mode 100644 index 0000000..ae47d0f --- /dev/null +++ b/docs/adr/README.md @@ -0,0 +1,25 @@ +# Architecture Decision Records + +One short record per significant decision: context, decision, alternatives, +consequences, sources. + +Status values: `accepted` · `provisional` (right for Alpha, revisit later) · +`open` (needs evidence before implementing) · `superseded`. + +| ADR | Decision | Status | +|---|---|---| +| [0001](0001-archiso-baseline.md) | archiso is the baseline; do not fork it | accepted | +| [0002](0002-kernel-linux-cachyos.md) | Ship `linux-cachyos`; no custom kernel | accepted | +| [0003](0003-cachyos-as-supplier.md) | CachyOS is a component supplier, not a template | accepted | +| [0004](0004-hyprland-desktop.md) | Hyprland from stable repos; no `-git` | accepted | +| [0005](0005-sddm-display-manager.md) | SDDM, X11 greeter, Wayland session | provisional | +| [0006](0006-networkmanager.md) | NetworkManager alone | accepted | +| [0007](0007-pipewire-audio.md) | PipeWire + WirePlumber, explicitly enabled | accepted | +| [0008](0008-calamares-offline.md) | Calamares, offline unpackfs, own config dir | accepted | +| [0009](0009-grub-for-installed-system.md) | GRUB on the installed system | provisional | +| [0010](0010-skel-as-config-source.md) | `/etc/skel` is the single dotfile source | accepted | +| [0011](0011-filesystem-ext4-default.md) | ext4 default; Btrfs only with a full rollback lifecycle | provisional | +| [0012](0012-no-custom-kernel-yet.md) | No SimulationOS kernel fork | accepted | +| [0013](0013-profiles-as-metapackages.md) | Capability profiles as meta-packages | open | +| [0014](0014-nftables-firewall.md) | nftables default policy | open | +| [0015](0015-single-build-engine.md) | One build engine: `./build.sh` | accepted | diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..55950ae --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,406 @@ +# SimulationOS architecture + +Design decisions and the reasoning behind them. Where a choice differs from +Arch or CachyOS, this document says which behaviour is upstream and which is a +SimulationOS decision. + +--- + +## 1. Layering + +``` +UPSTREAM ARCHISO BEHAVIOR the baseline: profile format, boot modes, + initramfs hooks, airootfs overlay semantics +CACHYOS-SPECIFIC BEHAVIOR a component supplier: kernel, installer build, + keyring/mirrorlist, two packages Arch lacks +SIMULATIONOS DECISION identity, live session, desktop, installer config +``` + +SimulationOS does not fork archiso and does not copy the CachyOS ISO profile. +It is an archiso profile that consumes CachyOS packages. + +--- + +## 2. archiso profile + +### Boot modes + +**UPSTREAM:** archiso consolidated its boot mode names. `bios.syslinux.mbr` and +`bios.syslinux.eltorito` became `bios.syslinux`; the four +`uefi-{x64,ia32}.systemd-boot.{esp,eltorito}` names became a single +`uefi.systemd-boot`. The old names still exist as shims that emit a +deprecation warning. `mkarchiso` also **rejects** `uefi.systemd-boot` and +`uefi.grub` used together. + +**SIMULATIONOS DECISION:** + +```bash +bootmodes=('bios.syslinux' 'uefi.systemd-boot') +``` + +`uefi.systemd-boot` already covers x64 plus mixed-mode IA32 on x86_64, so no +separate IA32 entry is needed. + +### `grub/` + +**UPSTREAM:** `mkarchiso`'s `_make_bootmodes()` calls +`_make_common_grubenv_and_loopbackcfg` whenever no `*grub*` boot mode is in +use, which installs `grub/loopback.cfg` onto the ISO. `grub/grub.cfg`, by +contrast, is only read by `_make_common_bootmode_grub_cfg`, which only +`_make_bootmode_uefi.grub` calls. + +**SIMULATIONOS DECISION:** keep `grub/loopback.cfg` (it lets an existing GRUB +boot this ISO from a file), delete `grub/grub.cfg` (unreachable without a +`uefi.grub` boot mode, which we cannot have alongside systemd-boot). +`validate-profile.sh` enforces this invariant. + +### Removed variables + +`buildmodes=('iso')` is the implicit default and upstream dropped it from both +its profiles. `iso_icon`, `profiles_description`, `install_dir_disktop` and +`kernel_parameters` are **not** variables `mkarchiso` reads — they were noise. +The validator fails if any reappear. + +### Build order matters + +`mkarchiso` runs `_make_custom_airootfs` **before** `_make_packages`. The +`airootfs/` overlay is laid down first and pacstrap installs on top of it. +A file we ship at a path a package also owns is therefore only safe when that +path is in the package's `backup` array — otherwise pacstrap aborts with a file +conflict. + +Verified backup-array members that SimulationOS overlays safely: + +| Path | Owning package | In `backup`? | +|---|---|---| +| `/etc/pacman.conf` | `pacman` | yes | +| `/etc/passwd`, `/etc/group`, `/etc/gshadow` | `filesystem` | yes | +| `/etc/hosts`, `/etc/issue` | `filesystem` | yes | + +This is also why SimulationOS **removed** `airootfs/etc/pacman.d/mirrorlist`: +the hand-written CachyOS-forcing mirrorlist both hard-coded mirrors and sat at +a path owned by `pacman-mirrorlist`. The package now provides it and the +inherited `uncomment-mirrors.hook` uncomments it, which is upstream behaviour. + +--- + +## 3. Kernel + +**CACHYOS:** `linux-cachyos`'s `PKGBUILD` sets `pkgbase="linux-cachyos"` and +installs the image as `$modulesdir/vmlinuz` with a `pkgbase` marker file. The +standard `mkinitcpio` pacman hook then produces: + +``` +/boot/vmlinuz-linux-cachyos +/boot/initramfs-linux-cachyos.img +/boot/initramfs-linux-cachyos-fallback.img +/etc/mkinitcpio.d/linux-cachyos.preset +``` + +**The bug this replaced:** the profile previously had *three* mutually +inconsistent names — `linux-cachyos` installed, boot entries pointing at +`vmlinuz-linux`, and a hand-written `/etc/mkinitcpio.d/linux.preset` naming a +nonexistent `vmlinuz-linux-simos`. Nothing lined up and the ISO could not boot. + +**SIMULATIONOS DECISION:** one name, `linux-cachyos`, everywhere: the package +list, the systemd-boot entries, the syslinux entries, the PXE entries and +`loopback.cfg`. The custom preset is deleted — upstream archiso removed its own +`linux.preset` for the same reason ("the default preset is good enough"). The +validator derives the expected filenames from the package list and fails on any +drift. + +**Microcode** needs no manual handling: `mkinitcpio`'s `microcode` hook (in +`archiso.conf`) embeds it, and `mkarchiso` detects the embedded case via +`_check_if_initramfs_has_ucode`, copying external ucode images and injecting +them into boot entries only when required. + +--- + +## 4. CachyOS repository integration + +Only four things genuinely require CachyOS: + +| Package | Why | +|---|---| +| `linux-cachyos` | the kernel SimulationOS is defined by | +| `cachyos-calamares` | Calamares is not in the Arch repositories | +| `ckbcomp`, `mkinitcpio-openswap` | `cachyos-calamares` dependencies, absent from Arch | + +Plus `cachyos-keyring` and `cachyos-mirrorlist` so the installed system retains +access. + +**SIMULATIONOS DECISION — repository order.** Arch repos are listed *first*: + +``` +[core] [extra] [multilib] [cachyos] +``` + +A package present in both comes from Arch. SimulationOS uses CachyOS for what +is exclusive to it, not as a wholesale replacement for the Arch package set. +This is the opposite of CachyOS's own ordering and is intentional: it keeps the +dependency surface predictable. + +**SIMULATIONOS DECISION — no developer-specific files.** The build-host +`pacman.conf` declares `[cachyos]` with explicit `Server =` URLs instead of +`Include = /etc/pacman.d/cachyos-mirrorlist`. The previous version required a +file that merely happened to exist on one machine. The *keyring* is still a +genuine host prerequisite, because pacstrap verifies signatures against the +host keyring — so `build-iso.sh` checks for `cachyos-keyring` and for key +`F3B607488DB35A47`, and fails early with the exact provisioning commands. +Signature verification is never disabled. (`DisableSandbox` was also removed +from `pacman.conf`.) + +The live system's `/etc/pacman.conf` keeps +`Include = /etc/pacman.d/cachyos-mirrorlist`, which is correct there because +the `cachyos-mirrorlist` package is installed. + +--- + +## 5. The live user + +**UPSTREAM:** `mkarchiso`'s `_make_customize_airootfs` runs *after* packages +are installed. For every entry in `airootfs/etc/passwd` with UID 1000–59999 and +a valid home, it creates the home directory if missing, copies `/etc/skel/.` +into it, `chmod 0750`s it and `chown -hR`s it to that user. + +That is a real, supported mechanism — `/etc/skel` *is* applied, provided the +account is declared in `airootfs/etc/passwd`. + +**SIMULATIONOS DECISION:** put the desktop configuration in +`airootfs/etc/skel/.config/` and let archiso materialise +`/home/liveuser/.config/...` with correct ownership. One source of truth, and +Calamares' `users` module copies the same `/etc/skel` for the installed user — +so the live desktop and the installed desktop are identical by construction, +with no duplicated dotfiles. + +Live-only concessions are named so they can be removed deterministically: + +| Path | Purpose | +|---|---| +| `/etc/sddm.conf.d/20-simulationos-live-autologin.conf` | autologin liveuser | +| `/etc/sudoers.d/10-simulationos-live` | NOPASSWD sudo | +| `/etc/polkit-1/rules.d/49-simulationos-live-nopasswd.rules` | permissive polkit | +| `/etc/systemd/system/getty@tty1.service.d/autologin.conf` | tty autologin | + +Everything with `-live-` in the name is stripped by `simulationos-deloop`. + +--- + +## 6. Graphical session + +**SIMULATIONOS DECISION: SDDM, X11 greeter, Wayland session.** + +`sddm` hard-depends on `xorg-server` and `xorg-xauth`, so its default +`DisplayServer=x11` greeter works with no extra packages. Its Wayland greeter +would need `weston` (`CompositorCommand=weston --shell=kiosk`), which is not +shipped. The greeter launches `hyprland.desktop` from +`/usr/share/wayland-sessions/`, which the `hyprland` package provides. + +The theme is `maldives`, one of the three themes (`elarun`, `maldives`, `maya`) +that ship inside the `sddm` package. The previous config specified `breeze`, +which requires Plasma and was not installed. + +Enablement is explicit: `/etc/systemd/system/display-manager.service` is a +symlink to `sddm.service`, and `default.target` points at `graphical.target`. +The inherited `dmcheck` script, which guessed at a display manager and was +never invoked by anything, was deleted. + +### Audio enablement + +**UPSTREAM:** the `pipewire`, `pipewire-pulse` and `wireplumber` packages ship +user units but **no** `.wants` symlinks, so nothing enables them by file. + +**SIMULATIONOS DECISION:** declare enablement explicitly in +`airootfs/etc/systemd/user/`, from the units' actual `[Install]` sections: + +| Unit | `[Install]` | Symlink shipped | +|---|---|---| +| `pipewire.socket` | `WantedBy=sockets.target` | `sockets.target.wants/` | +| `pipewire.service` | `WantedBy=default.target` | `default.target.wants/` | +| `pipewire-pulse.socket` | `WantedBy=sockets.target` | `sockets.target.wants/` | +| `pipewire-pulse.service` | `WantedBy=default.target` | `default.target.wants/` | +| `wireplumber.service` | `WantedBy=pipewire.service`, `Alias=pipewire-session-manager.service` | `pipewire.service.wants/` + the alias | + +--- + +## 7. Networking + +**UPSTREAM:** archiso's releng profile uses `systemd-networkd` + `iwd` + +`systemd-resolved`, which suits a headless install medium. + +**SIMULATIONOS DECISION:** NetworkManager only. A Hyprland desktop wants +`nm-applet` and `nm-connection-editor`, and Calamares' `networkcfg` module +migrates NetworkManager connections into the installed system. Running two +network stacks is a classic source of non-deterministic breakage, so +`systemd-networkd`, its `.network` files, `iwd` and the statically enabled +`wpa_supplicant.service` were all removed. `wpa_supplicant` stays installed +because NetworkManager activates it over D-Bus. + +`systemd-resolved` was dropped with it, along with the +`/etc/resolv.conf -> stub-resolv.conf` symlink that depended on it; +NetworkManager manages `/etc/resolv.conf` directly. The validator fails if both +stacks are ever enabled at once. + +--- + +## 8. Hardware + +Generic support: `linux-firmware`, `sof-firmware`, `mesa`, `vulkan-radeon`, +`vulkan-intel`, `vulkan-swrast`, `xorg-xwayland`, `bluez`. + +**SIMULATIONOS DECISION — no `chwd`, no NVIDIA scripts (Alpha).** The profile +inherited `nvidia-module-loader`, `remove-nvidia` and `removeun`, all of which +call CachyOS's `chwd` hardware-detection tool. `chwd` was never in the package +list and nothing invoked those scripts, so the "NVIDIA support" was inert. The +honest choice for Alpha is removal rather than shipping a half-working +hardware-detection path. NVIDIA hardware falls back to the in-kernel `nouveau` +driver. + +`cursor:no_hardware_cursors = true` is set in the Hyprland config because +SimulationOS is expected to be evaluated in a VM, where hardware cursor planes +are frequently broken and the pointer disappears. + +--- + +## 9. Desktop configuration + +The inherited Hyprland and Waybar configuration was the author's personal +laptop setup and was replaced wholesale rather than patched. It contained: + +- `/mnt/m.2_ssd/Linux/Wallpapers/1354205.jpeg` as the wallpaper +- `~/.scripts/Acer/PredatorSense/rgbkb/rgbkb.service.sh` on autostart +- **`exec-once = brightnessctl set 0%`** — a black screen on first login +- a hardcoded USB audio sink, a hardcoded `SYNA7DB5:00` touchpad, a hardcoded + `eDP-2` output +- dependencies on `grimblast`, `auto-cpufreq`, `pamixer` and the ML4W dotfile + framework, none of them shipped +- both `hyprpaper.conf` and `swww` autostart (two wallpaper daemons) +- both `monitor.conf` and `monitors.conf`, plus several config files that were + shipped but never sourced + +**SIMULATIONOS DECISION:** one `hyprland.conf` plus a deliberately empty +`monitors.conf` for per-machine overrides. Every `exec-once` and every keybind +target maps to a package in `packages.x86_64` or to a script in +`airootfs/usr/local/bin/`. Waybar uses **built-in modules only** — no custom +scripts — so a missing helper can never blank the bar. One wallpaper daemon +(`hyprpaper`), one launcher (`wofi`), one terminal (`kitty`), one file manager +(`thunar`), one notification daemon (`mako`), one polkit agent +(`hyprpolkitagent`) and one screen locker (`hyprlock`). + +The validator enforces all of this: sourced files must exist, exec targets must +be shipped, the wallpaper must exist, only one wallpaper daemon may autostart, +and `brightnessctl set 0%` is a hard error. + +The wallpaper is a real generated asset +(`airootfs/usr/share/backgrounds/simulationos/simulationos-alpha.png`, +1920x1080), reproducible via `scripts/make-wallpaper.py`. + +`.bashrc` was also fixed: it aliased `rm` to `trash-put` and `n` to `nvim` +without shipping either, so `rm` was broken in the live session. + +Two other inherited defects worth recording: `airootfs/etc/hosts` contained +*only* a hardcoded GitHub IP with no `localhost` entries, and +`airootfs/etc/polkit-1/rules.d/sddm.conf.d/autologin.conf` was an SDDM config +filed inside polkit's rules directory, where SDDM would never read it. + +--- + +## 10. Installer + +### Why the configuration is not in `/etc/calamares` + +`cachyos-calamares` owns roughly sixty files under `/etc/calamares/modules/` +and declares **no `backup` array**. Because the airootfs overlay is laid down +*before* pacstrap, shipping our own files at those paths would be a hard +pacstrap file conflict and the build would fail. + +**SIMULATIONOS DECISION:** ship a self-contained tree at +`/usr/share/simulationos/calamares/` and launch + +``` +calamares -c /usr/share/simulationos/calamares +``` + +Calamares' `-c/--config` sets `appDataDir`, and when that is overridden both +`moduleConfigurationCandidates()` and `brandingFileCandidates()` resolve +**only** inside it. So settings, module configs and branding all come from one +SimulationOS-owned directory, with zero chance of silently inheriting CachyOS +defaults and zero file conflicts. + +### Installation model + +Offline, via `unpackfs`: the live SquashFS at +`/run/archiso/bootmnt/arch/x86_64/airootfs.sfs` (derived from `install_dir` +and `arch` in `profiledef.sh`, and checked by the validator) is copied to the +target. Simple, network-free, and the live desktop is by definition what gets +installed. + +Sequence, and why the order is what it is: + +``` +partition -> mount -> unpackfs -> machineid -> fstab -> locale -> keyboard +-> localecfg -> users -> networkcfg -> hwclock -> services-systemd -> packages +-> removeuser -> shellprocess@deloop -> initcpiocfg -> initcpio +-> grubcfg -> bootloader -> umount +``` + +- `removeuser` runs after `users`, so the real account exists first. +- **`shellprocess@deloop` must run before `initcpio`.** It deletes + `/etc/mkinitcpio.conf.d/archiso.conf`; if that drop-in survived, `mkinitcpio` + would build another *archiso* initramfs and the installed system would not + boot without the ISO. This ordering is the single most load-bearing detail in + the installer, and the validator checks that `deloop` still handles it. +- `packages` uses `try_remove` for `cachyos-calamares` and `gparted`, so the + installed system does not carry its own installer. `try_remove` cannot fail + the installation. + +### Undoing the live medium + +`simulationos-deloop` runs inside the target chroot and removes: SDDM +autologin, tty autologin, the NOPASSWD sudoers file (replacing it with a +validated password-prompting `%wheel` rule), the permissive polkit rule, the +archiso initramfs hook, archiso-only units (`livecd-talk`, +`livecd-alsa-unmuter`, `pacman-init`, the gnupg mount), the gpt-auto-generator +mask, the volatile-journal and do-not-suspend drop-ins, and `/home/liveuser`. + +It also **locks the root account**. This matters: the live medium ships +`root::` — an empty password — and `unpackfs` copies `/etc/shadow` verbatim, so +without this step every installed system would have a passwordless root. +Calamares is configured with `setRootPassword: false` (a sudo-only model), so +locking root is the correct completion of that design. + +The script never deletes the file it is executing from; removing +`/usr/share/simulationos` is a separate command listed after it in +`shellprocess_deloop.conf`. + +### Installed-system bootloader + +**SIMULATIONOS DECISION: GRUB.** The ISO uses syslinux + systemd-boot; the +installed system uses GRUB. These are separate concerns and conflating them is +a common mistake. GRUB covers BIOS and UEFI with one code path, which is the +right trade for an Alpha. `grubcfg` writes `/etc/default/grub` with +`GRUB_DISTRIBUTOR="SimulationOS"`. + +--- + +## 11. Validation + +`scripts/validate-profile.sh` is the guard against regressions. It was itself +verified by fault injection — ten deliberate regressions were introduced into a +scratch copy and every one was caught: + +| Injected fault | Caught | +|---|---| +| kernel drift in a boot entry | yes | +| deprecated bootmode reintroduced | yes | +| `broadcom-wl` (removed from Arch) reintroduced | yes | +| personal `/mnt/m.2_ssd` path returns | yes | +| `brightnessctl set 0%` reintroduced | yes | +| Hyprland launches an unshipped binary | yes | +| second wallpaper daemon added | yes | +| `deloop` stops removing the archiso hook | yes | +| `doAutologin: true` in `users.conf` | yes | +| Calamares module config or display manager deleted | yes | + +The checks deliberately ignore comment text, so documentation can name a banned +tool without tripping its own rule. diff --git a/docs/research/sources.md b/docs/research/sources.md new file mode 100644 index 0000000..88d9d9a --- /dev/null +++ b/docs/research/sources.md @@ -0,0 +1,187 @@ +# SimulationOS research sources + +Primary-source findings behind the architecture. Conclusions only — upstream +documentation is not copied here. Every entry records what was checked, where, +and when. + +All entries accessed **2026-09-27 / 2026-09-28** unless noted. + +--- + +## archiso + +**Source:** `https://gitlab.archlinux.org/archlinux/archiso` — `archiso/mkarchiso` +(2011 lines), `docs/README.profile.rst`, `CHANGELOG.rst`, `configs/releng/`. + +| Finding | Evidence | +|---|---| +| Valid boot modes are exactly `bios.syslinux`, `uefi.grub`, `uefi.systemd-boot` | `README.profile.rst`, bootmodes section | +| The six older names are deprecated shims that warn and alias | `mkarchiso:1001-1096` | +| `uefi.systemd-boot` + `uefi.grub` together are **rejected** | `mkarchiso:1050-1052` | +| `uefi.systemd-boot` covers x64 **and** mixed-mode IA32 on x86_64 | `mkarchiso:906-910` | +| `grub/loopback.cfg` is installed when **no** `*grub*` bootmode is set | `mkarchiso:_make_bootmodes()`, lines 473-481 | +| `grub/grub.cfg` is read **only** by `uefi.grub` | `mkarchiso:745` | +| `buildmodes` default is `iso`; upstream removed it from its profiles | `CHANGELOG.rst` "Removed" | +| Upstream removed its custom `/etc/mkinitcpio.d/linux.preset` | `CHANGELOG.rst`: "The default preset is good enough" | +| `broadcom-wl` was removed from Arch; upstream dropped its modprobe drop-in | `CHANGELOG.rst` | +| `airootfs` is copied **before** pacstrap | `mkarchiso:1846` then `:1847` | +| `/etc/skel` **is** copied into every `airootfs/etc/passwd` home with UID 1000-59999, created and `chown -hR`'d | `_make_customize_airootfs()`, runs at `mkarchiso:1852` | +| `file_permissions` with a trailing `/` applies recursively | `README.profile.rst`; `_make_custom_airootfs()` | +| ISO filename is `${iso_name}-${iso_version}-${arch}.iso` | `mkarchiso:1930` | +| Boot-entry placeholders: `%ARCHISO_LABEL% %ARCHISO_UUID% %INSTALL_DIR% %KERNEL_PARAMS% %ARCH%` | `mkarchiso:884-889` | +| Microcode is handled automatically; external ucode images are injected only when not embedded | `_check_if_initramfs_has_ucode()`, `mkarchiso:620-630` | +| SquashFS lands at `//airootfs.sfs`; the medium mounts at `/run/archiso/bootmnt` | `mkarchiso:190`; `mkinitcpio-archiso` hook line 168 | +| `mkinitcpio` + `mkinitcpio-archiso` are mandatory packages | `README.profile.rst` | +| `mkarchiso` can run unprivileged via `unshare` (`-N`) when user namespaces exist | `_make_packages()`, `pacstrap -N` branch | + +**Decision:** treat archiso as the architectural baseline and do not fork it. + +--- + +## pacman / packaging + +| Finding | Evidence | +|---|---| +| `/etc/pacman.conf` is in the `pacman` package's `backup` array | Arch `pacman` PKGBUILD, `backup=(etc/pacman.conf ...)` | +| `/etc/passwd`, `/etc/group`, `/etc/gshadow`, `/etc/hosts`, `/etc/issue` are in `filesystem`'s `backup` array | Arch `filesystem` PKGBUILD | +| Arch ships `system-preset/99-default.preset` = `disable *`, but **no** catch-all user preset | `systemd` package file list | + +**Consequence:** an `airootfs` overlay is only safe at a package-owned path if +that path is a backup file. This is why the SimulationOS Calamares config is +*not* in `/etc/calamares`, and why the hand-written mirrorlist was removed. +It is also why pipewire user units are enabled by explicit symlink rather than +by relying on presets. + +--- + +## CachyOS + +**Source:** `github.com/CachyOS/{linux-cachyos,cachyos-calamares,CachyOS-Live-ISO,cachyos-repo-add-script}`, +plus the live repository database at `mirror.cachyos.org/repo/x86_64/cachyos/`. + +| Finding | Evidence | +|---|---| +| `pkgbase=linux-cachyos`; image installed as `$modulesdir/vmlinuz` with a `pkgbase` marker | `linux-cachyos/PKGBUILD:177,612,615` | +| Therefore the installed files are `vmlinuz-linux-cachyos`, `initramfs-linux-cachyos.img`, preset `linux-cachyos.preset` | standard mkinitcpio hook behaviour | +| `cachyos-calamares` owns ~60 files under `/etc/calamares/modules/` and declares **no** `%BACKUP%` | `cachyos.files` / `cachyos.db` entry for `cachyos-calamares-3.4.2-4` | +| It `provides`/`conflicts` `calamares`; deps include `ckbcomp`, `mkinitcpio-openswap`, `kpmcore`, qt6 stack | `cachyos.db` `%DEPENDS%` | +| `ckbcomp` and `mkinitcpio-openswap` exist **only** in the CachyOS repo | Arch package search returns NONE; present in `cachyos` | +| Repo provisioning is key `F3B607488DB35A47` via keyserver.ubuntu.com, `--lsign-key`, then the keyring package | `cachyos-repo.sh:156-164` | +| `cachyos-calamares` is a full Calamares **fork**, not just configs | repository layout (`src/`, `CMakeLists.txt`) | + +**Decision:** use CachyOS as a component supplier only. Do not fork Calamares, +do not adopt the CachyOS ISO profile, do not mirror their repo ordering. + +**Verified 2026-09-28** by resolving the whole SimulationOS package set inside a +real `linux/amd64` Arch container: 144 requested → 577 resolved, of which +exactly 6 come from `[cachyos]`. + +--- + +## Calamares + +**Source:** `github.com/CachyOS/cachyos-calamares` (the build SimulationOS +installs) — `src/calamares/main.cpp`, `CalamaresApplication.cpp`, +`src/libcalamares/modulesystem/Module.cpp`. + +| Finding | Evidence | +|---|---| +| `-c/--config ` calls `Calamares::setAppDataDir(dir)` | `main.cpp:75-95` | +| When appDataDir is overridden, module configs resolve **only** under `/modules/` | `Module.cpp:50-56` | +| When appDataDir is overridden, branding resolves **only** under `/branding/` | `CalamaresApplication.cpp: brandingFileCandidates()` | +| Otherwise branding prefers `/etc/calamares/branding/` then `/usr/share/calamares/branding/` | same function | +| `/etc/calamares/settings.conf` is *not* shipped by the package; `/usr/share/calamares/settings{,_offline,_online}.conf` are | `cachyos-calamares` file list | +| Modules available in 3.4.2 include `unpackfs`, `removeuser`, `packages`, `services-systemd`, `initcpiocfg`, `initcpio`, `grubcfg`, `bootloader`, `networkcfg`, `machineid`, `summary` | `usr/lib/calamares/modules/` listing | + +**Decision:** ship a self-contained config tree at +`/usr/share/simulationos/calamares` and launch with `-c`. This is the only +approach that is simultaneously conflict-free and immune to silently +inheriting CachyOS defaults. + +--- + +## Hyprland and the Wayland desktop + +Package availability confirmed against `archlinux.org/packages` (official repos +only; no AUR, no `-git`). + +| Area | Chosen | Note | +|---|---|---| +| compositor | `hyprland` (extra) | ships `/usr/share/wayland-sessions/hyprland.desktop` | +| bar / launcher / term / files | `waybar`, `wofi`, `kitty`, `thunar` + `gvfs` | all extra | +| notifications | `mako` | simplest reliable daemon | +| polkit agent | `hyprpolkitagent` | ships `hyprpolkitagent.service` user unit | +| lock | `hyprlock` | so the power menu's Lock is not a no-op | +| wallpaper | `hyprpaper` only | `swww` is **not** in the Arch repos | +| portals | `xdg-desktop-portal` + `-hyprland` + `-gtk` | | +| screenshots / clipboard | `grim`, `slurp`, `wl-clipboard`, `cliphist` | | + +`rofi-wayland` and `libva-mesa-driver` no longer exist as separate packages. + +**Decision:** stable repo packages only. Hyprland's ecosystem has coupled ABI +expectations, so `-git` packages are out of scope for a distribution baseline. + +--- + +## Display manager + +**Source:** the `sddm` 0.21.0-7 package contents and Arch PKGBUILD. + +| Finding | Evidence | +|---|---| +| Default `DisplayServer=x11`; `xorg-server` and `xorg-xauth` are **hard dependencies** | `/usr/lib/sddm/sddm.conf.d/default.conf`; PKGBUILD `depends=` | +| The Wayland greeter needs `weston` (`CompositorCommand=weston --shell=kiosk`) | same default.conf | +| Bundled themes are exactly `elarun`, `maldives`, `maya` | `/usr/share/sddm/themes/` | +| SDDM ships **no** `/etc/sddm.conf` or `/etc/sddm.conf.d/`, so those paths are free | package file list | +| Wayland sessions are read from `/usr/share/wayland-sessions` | default.conf `[Wayland] SessionDir` | + +**Decision:** X11 greeter launching a Wayland session; theme `maldives` +(guaranteed present). The previously configured `breeze` needs Plasma. + +--- + +## Audio + +`[Install]` sections read from the actual packaged unit files, not from +documentation: + +| Unit | `[Install]` | +|---|---| +| `pipewire.socket` | `WantedBy=sockets.target` | +| `pipewire.service` | `WantedBy=default.target`, `Also=pipewire.socket` | +| `pipewire-pulse.socket` | `WantedBy=sockets.target` | +| `pipewire-pulse.service` | `WantedBy=default.target` | +| `wireplumber.service` | `WantedBy=pipewire.service`, `Alias=pipewire-session-manager.service` | + +None of these packages ship `.wants` symlinks. + +**Decision:** PipeWire + WirePlumber, enabled by explicit symlinks under +`/etc/systemd/user/`. **Rejected:** relying on systemd presets (not applied at +package-install time on Arch) and running PulseAudio alongside PipeWire. + +--- + +## Networking + +**Decision:** NetworkManager alone, with `wpa_supplicant` installed but +D-Bus-activated. +**Alternatives considered:** upstream releng's `systemd-networkd` + `iwd` + +`systemd-resolved` — rejected because it targets headless installs, has no +Hyprland-friendly GUI, and Calamares' `networkcfg` module migrates +NetworkManager connections into the installed system. +`systemd-resolved` was dropped with it so only one component owns +`/etc/resolv.conf`. + +--- + +## Still to research (not yet decided) + +These are deliberately **not** implemented yet; see `docs/adr/` for status. + +- nftables default policy +- filesystem strategy (ext4 vs Btrfs + whether we can own the full snapshot/rollback lifecycle) +- zram sizing, measured rather than copied +- kernel policy beyond `linux-cachyos` (fallback/LTS kernel) +- profile meta-package mechanism (package group vs meta-package) +- SimulationOS package repository, keyring and signing +- GPU driver selection matrix, especially 32-bit Vulkan provider ordering for Steam diff --git a/efiboot/loader/entries/01-archiso-x86_64-linux.conf b/efiboot/loader/entries/01-archiso-x86_64-linux.conf deleted file mode 100644 index bc8ab33..0000000 --- a/efiboot/loader/entries/01-archiso-x86_64-linux.conf +++ /dev/null @@ -1,5 +0,0 @@ -title Arch Linux install medium (x86_64, UEFI) -sort-key 01 -linux /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux -initrd /%INSTALL_DIR%/boot/x86_64/initramfs-linux.img -options archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID% diff --git a/efiboot/loader/entries/01-simulationos-linux.conf b/efiboot/loader/entries/01-simulationos-linux.conf new file mode 100644 index 0000000..83aa785 --- /dev/null +++ b/efiboot/loader/entries/01-simulationos-linux.conf @@ -0,0 +1,5 @@ +title SimulationOS (%ARCH%, UEFI) +sort-key 01 +linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux-cachyos +initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux-cachyos.img +options archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID% console=ttyS0,115200 console=tty0 %KERNEL_PARAMS% diff --git a/efiboot/loader/entries/02-archiso-x86_64-speech-linux.conf b/efiboot/loader/entries/02-archiso-x86_64-speech-linux.conf deleted file mode 100644 index c0cb1c8..0000000 --- a/efiboot/loader/entries/02-archiso-x86_64-speech-linux.conf +++ /dev/null @@ -1,5 +0,0 @@ -title Arch Linux install medium (x86_64, UEFI) with speech -sort-key 02 -linux /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux -initrd /%INSTALL_DIR%/boot/x86_64/initramfs-linux.img -options archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID% accessibility=on diff --git a/efiboot/loader/entries/02-simulationos-speech-linux.conf b/efiboot/loader/entries/02-simulationos-speech-linux.conf new file mode 100644 index 0000000..d68f78f --- /dev/null +++ b/efiboot/loader/entries/02-simulationos-speech-linux.conf @@ -0,0 +1,5 @@ +title SimulationOS (%ARCH%, UEFI) with speech +sort-key 02 +linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux-cachyos +initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux-cachyos.img +options archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID% accessibility=on console=ttyS0,115200 console=tty0 %KERNEL_PARAMS% diff --git a/efiboot/loader/entries/03-archiso-x86_64-memtest86+.conf b/efiboot/loader/entries/03-simulationos-memtest86+x64.conf similarity index 51% rename from efiboot/loader/entries/03-archiso-x86_64-memtest86+.conf rename to efiboot/loader/entries/03-simulationos-memtest86+x64.conf index d0b305c..fd8af77 100644 --- a/efiboot/loader/entries/03-archiso-x86_64-memtest86+.conf +++ b/efiboot/loader/entries/03-simulationos-memtest86+x64.conf @@ -1,3 +1,4 @@ -title Memtest86+ +title Memtest86+ (RAM test) sort-key 03 efi /boot/memtest86+/memtest.efi +architecture x64 diff --git a/efiboot/loader/loader.conf b/efiboot/loader/loader.conf index 2d137aa..366e61f 100644 --- a/efiboot/loader/loader.conf +++ b/efiboot/loader/loader.conf @@ -1,3 +1,3 @@ timeout 15 -default 01-archiso-x86_64-linux.conf +default 01-simulationos-linux.conf beep on diff --git a/grub/grub.cfg b/grub/grub.cfg deleted file mode 100644 index 25194a3..0000000 --- a/grub/grub.cfg +++ /dev/null @@ -1,107 +0,0 @@ -# Load partition table and file system modules -insmod part_gpt -insmod part_msdos -insmod fat -insmod iso9660 -insmod ntfs -insmod ntfscomp -insmod exfat -insmod udf - -# Use graphics-mode output -if loadfont "${prefix}/fonts/unicode.pf2" ; then - insmod all_video - set gfxmode="auto" - terminal_input console - terminal_output console -fi - -# Enable serial console -insmod serial -insmod usbserial_common -insmod usbserial_ftdi -insmod usbserial_pl2303 -insmod usbserial_usbdebug -if serial --unit=0 --speed=115200; then - terminal_input --append serial - terminal_output --append serial -fi - -# Get a human readable platform identifier -if [ "${grub_platform}" == 'efi' ]; then - archiso_platform='UEFI' - if [ "${grub_cpu}" == 'x86_64' ]; then - archiso_platform="x64 ${archiso_platform}" - elif [ "${grub_cpu}" == 'i386' ]; then - archiso_platform="IA32 ${archiso_platform}" - else - archiso_platform="${grub_cpu} ${archiso_platform}" - fi -elif [ "${grub_platform}" == 'pc' ]; then - archiso_platform='BIOS' -else - archiso_platform="${grub_cpu} ${grub_platform}" -fi - -# Set default menu entry -default=archlinux -timeout=15 -timeout_style=menu - - -# Menu entries - -menuentry "Arch Linux install medium (%ARCH%, ${archiso_platform})" --class arch --class gnu-linux --class gnu --class os --id 'archlinux' { - set gfxpayload=keep - linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID% - initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux.img -} - -menuentry "Arch Linux install medium with speakup screen reader (%ARCH%, ${archiso_platform})" --hotkey s --class arch --class gnu-linux --class gnu --class os --id 'archlinux-accessibility' { - set gfxpayload=keep - linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID% accessibility=on - initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux.img -} - - -if [ "${grub_platform}" == 'efi' -a "${grub_cpu}" == 'x86_64' -a -f '/boot/memtest86+/memtest.efi' ]; then - menuentry 'Run Memtest86+ (RAM test)' --class memtest86 --class memtest --class gnu --class tool { - set gfxpayload=800x600,1024x768 - linux /boot/memtest86+/memtest.efi - } -fi -if [ "${grub_platform}" == 'pc' -a -f '/boot/memtest86+/memtest' ]; then - menuentry 'Run Memtest86+ (RAM test)' --class memtest86 --class memtest --class gnu --class tool { - set gfxpayload=800x600,1024x768 - linux /boot/memtest86+/memtest - } -fi -if [ "${grub_platform}" == 'efi' ]; then - if [ "${grub_cpu}" == 'x86_64' -a -f '/shellx64.efi' ]; then - menuentry 'UEFI Shell' --class efi { - chainloader /shellx64.efi - } - elif [ "${grub_cpu}" == "i386" -a -f '/shellia32.efi' ]; then - menuentry 'UEFI Shell' --class efi { - chainloader /shellia32.efi - } - fi - - menuentry 'UEFI Firmware Settings' --id 'uefi-firmware' { - fwsetup - } -fi - -menuentry 'System shutdown' --class shutdown --class poweroff { - echo 'System shutting down...' - halt -} - -menuentry 'System restart' --class reboot --class restart { - echo 'System rebooting...' - reboot -} - - -# GRUB init tune for accessibility -play 600 988 1 1319 4 diff --git a/grub/loopback.cfg b/grub/loopback.cfg index d7d5ece..5766853 100644 --- a/grub/loopback.cfg +++ b/grub/loopback.cfg @@ -1,4 +1,12 @@ # https://www.supergrubdisk.org/wiki/Loopback.cfg +# +# SimulationOS loopback entry point. +# +# NOTE: SimulationOS uses bootmodes=(bios.syslinux uefi.systemd-boot), so +# 'uefi.grub' is NOT a boot mode of this ISO and grub/grub.cfg is intentionally +# absent. mkarchiso still installs this file: _make_bootmodes() calls +# _make_common_grubenv_and_loopbackcfg whenever no *grub* bootmode is used, so +# loopback.cfg lets an already-installed GRUB boot this ISO from a file. # Search for the ISO volume search --no-floppy --set=archiso_img_dev --file "${iso_path}" @@ -7,37 +15,39 @@ probe --set archiso_img_dev_uuid --fs-uuid "${archiso_img_dev}" # Get a human readable platform identifier if [ "${grub_platform}" == 'efi' ]; then archiso_platform='UEFI' - if [ "${grub_cpu}" == 'x86_64' ]; then - archiso_platform="x64 ${archiso_platform}" - elif [ "${grub_cpu}" == 'i386' ]; then - archiso_platform="IA32 ${archiso_platform}" - else - archiso_platform="${grub_cpu} ${archiso_platform}" - fi elif [ "${grub_platform}" == 'pc' ]; then archiso_platform='BIOS' else - archiso_platform="${grub_cpu} ${grub_platform}" + archiso_platform="${grub_cpu}-${grub_platform}" +fi + +# Get the lowercase UEFI machine type short-name for architecture-specific tools +if [ "${grub_platform}" == 'efi' ]; then + if [ "${grub_cpu}" == 'x86_64' ]; then + uefi_machine_type_lower='x64' + elif [ "${grub_cpu}" == 'i386' ]; then + uefi_machine_type_lower='ia32' + fi fi # Set default menu entry -default=archlinux +default=simulationos timeout=15 timeout_style=menu # Menu entries -menuentry "Arch Linux install medium (%ARCH%, ${archiso_platform})" --class arch --class gnu-linux --class gnu --class os --id 'archlinux' { +menuentry "SimulationOS (%ARCH%, ${archiso_platform})" --class simulationos --class gnu-linux --class gnu --class os --id 'simulationos' { set gfxpayload=keep - linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux archisobasedir=%INSTALL_DIR% img_dev=UUID=${archiso_img_dev_uuid} img_loop="${iso_path}" - initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux.img + linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux-cachyos archisobasedir=%INSTALL_DIR% img_dev=UUID=${archiso_img_dev_uuid} img_loop="${iso_path}" %KERNEL_PARAMS% + initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux-cachyos.img } -menuentry "Arch Linux install medium with speakup screen reader (%ARCH%, ${archiso_platform})" --hotkey s --class arch --class gnu-linux --class gnu --class os --id 'archlinux-accessibility' { +menuentry "SimulationOS with speakup screen reader (%ARCH%, ${archiso_platform})" --hotkey s --class simulationos --class gnu-linux --class gnu --class os --id 'simulationos-accessibility' { set gfxpayload=keep - linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux archisobasedir=%INSTALL_DIR% img_dev=UUID=${archiso_img_dev_uuid} img_loop="${iso_path}" accessibility=on - initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux.img + linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux-cachyos archisobasedir=%INSTALL_DIR% img_dev=UUID=${archiso_img_dev_uuid} img_loop="${iso_path}" accessibility=on %KERNEL_PARAMS% + initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux-cachyos.img } @@ -53,14 +63,11 @@ if [ "${grub_platform}" == 'pc' -a -f '/boot/memtest86+/memtest' ]; then linux /boot/memtest86+/memtest } fi + if [ "${grub_platform}" == 'efi' ]; then - if [ "${grub_cpu}" == 'x86_64' -a -f '/shellx64.efi' ]; then - menuentry 'UEFI Shell' --class efi { - chainloader /shellx64.efi - } - elif [ "${grub_cpu}" == "i386" -a -f '/shellia32.efi' ]; then + if [ -f "/shell${uefi_machine_type_lower}.efi" ]; then menuentry 'UEFI Shell' --class efi { - chainloader /shellia32.efi + chainloader /shell${uefi_machine_type_lower}.efi } fi diff --git a/packages.x86_64 b/packages.x86_64 index b092a8c..df33414 100644 --- a/packages.x86_64 +++ b/packages.x86_64 @@ -1,133 +1,193 @@ -alsa-utils -amd-ucode -arch-install-scripts -archinstall -b43-fwcutter +# SimulationOS package list (x86_64) +# +# Grouped by purpose. Every entry is expected to resolve from: +# [core] [extra] [multilib] -> Arch Linux +# [cachyos] -> CachyOS (kernel, installer, keyring/mirrorlist) +# scripts/validate-profile.sh checks this file for structural problems; +# pacman resolves availability at build time. + +## ---------------------------------------------------------------- base system base -bcachefs-tools -bind -bolt -brltty -broadcom-wl -btrfs-progs -clonezilla -cloud-init -cryptsetup -darkhttpd -ddrescue -dhcpcd +bash +sudo +less +man-db +man-pages +nano +neovim +git +curl +wget +rsync +unzip +zip +p7zip +which +htop +btop +fastfetch +usbutils +lsscsi diffutils -dmidecode -dmraid -dnsmasq -dosfstools -e2fsprogs -edk2-shell -efibootmgr -espeakup -ethtool -exfatprogs -f2fs-tools -fatresize -foot-terminfo -fsarchiver -gpart -gpm -gptfdisk -grml-zsh-config -grub -hdparm -hyperv -intel-ucode -irssi -iw -iwd -jfsutils +pv +screen +tmux +terminus-font kitty-terminfo -ldns -less -lftp -libfido2 -libusb-compat -#linux +eza + +## ---------------------------------------------------------- kernel & firmware +# SimulationOS ships the CachyOS kernel. pkgbase is "linux-cachyos", so the +# installed files are /boot/vmlinuz-linux-cachyos and +# /boot/initramfs-linux-cachyos.img, and mkinitcpio generates +# /etc/mkinitcpio.d/linux-cachyos.preset. Boot entries must match those names. linux-cachyos -linux-cachyos-headers -linux-atm linux-firmware linux-firmware-marvell -livecd-sounds -lsscsi -lvm2 -lynx -man-db -man-pages -mc -mdadm -memtest86+ -memtest86+-efi +sof-firmware +amd-ucode +intel-ucode +# mkinitcpio and mkinitcpio-archiso are mandatory for archiso. mkinitcpio mkinitcpio-archiso -mkinitcpio-nfs-utils -mmc-utils -modemmanager -mtools -nano -nbd -ndisc6 -nfs-utils -nilfs-utils + +## ---------------------------------------------------------------- CachyOS repo +# Needed so the live system *and* the installed system keep working access to +# the repository the kernel came from. +cachyos-keyring +cachyos-mirrorlist +archlinux-keyring + +## -------------------------------------------------------------------- graphics +mesa +mesa-utils +vulkan-radeon +vulkan-intel +vulkan-swrast +vulkan-tools + +## ------------------------------------------------------------ Hyprland desktop +hyprland +hyprpaper +hyprpolkitagent +hyprlock +waybar +kitty +wofi +thunar +thunar-volman +gvfs +mako +libnotify +grim +slurp +wl-clipboard +cliphist +brightnessctl +polkit +xdg-desktop-portal +xdg-desktop-portal-hyprland +xdg-desktop-portal-gtk +xdg-user-dirs +xdg-utils +qt5-wayland +qt6-wayland +xorg-xwayland + +## ----------------------------------------------------------------------- fonts +ttf-dejavu +ttf-fira-sans +ttf-jetbrains-mono-nerd +ttf-nerd-fonts-symbols +noto-fonts +noto-fonts-emoji + +## ----------------------------------------------------------------------- themes +adwaita-icon-theme +papirus-icon-theme + +## ------------------------------------------------------------- display manager +sddm + +## ------------------------------------------------------------------------ audio +pipewire +pipewire-alsa +pipewire-pulse +pipewire-jack +wireplumber +pavucontrol +alsa-utils + +## ---------------------------------------------------------------------- network +networkmanager +network-manager-applet +nm-connection-editor +wpa_supplicant +wireless-regdb +wireless_tools +iw +ethtool +bind +tcpdump nmap +openssh +modemmanager +usb_modeswitch +b43-fwcutter + +## -------------------------------------------------------------------- bluetooth +bluez +bluez-utils +blueman + +## ------------------------------------------------------- filesystems & storage +btrfs-progs +e2fsprogs +xfsprogs +f2fs-tools +exfatprogs +dosfstools ntfs-3g nvme-cli -open-iscsi -open-vm-tools -openconnect -openpgp-card-tools -openssh -openvpn -partclone +mtools +gptfdisk parted -partimage -pcsclite -ppp -pptpclient -pv -qemu-guest-agent -refind -reflector -rsync -rxvt-unicode-terminfo -screen +cryptsetup +lvm2 +mdadm +hdparm sdparm -sequoia-sq -sg3_utils smartmontools -sof-firmware squashfs-tools -sudo -syslinux -systemd-resolvconf -tcpdump -terminus-font +dmidecode + +## -------------------------------------------------------------------- recovery +ddrescue testdisk -tmux -tpm2-tools -tpm2-tss -udftools -usb_modeswitch -usbmuxd -usbutils -neovim +partclone +fsarchiver +memtest86+ +memtest86+-efi + +## ------------------------------------------------------------------- installer +# cachyos-calamares provides /usr/bin/calamares (provides=calamares). +# SimulationOS supplies its own config tree, see +# airootfs/usr/share/simulationos/calamares/. +cachyos-calamares +gparted +inxi +arch-install-scripts +grub +efibootmgr +syslinux + +## -------------------------------------------------------------- accessibility +brltty +espeakup +livecd-sounds + +## ------------------------------------------------------------- VM guest agents +hyperv +open-vm-tools +qemu-guest-agent virtualbox-guest-utils-nox -vpnc -wireless-regdb -wireless_tools -wpa_supplicant -wvdial -xdg-utils -xfsprogs -xl2tpd -bash -eza -cachyos-keyring -cachyos-mirrorlist diff --git a/pacman.conf b/pacman.conf index c4dd9b1..5d549e4 100644 --- a/pacman.conf +++ b/pacman.conf @@ -1,105 +1,48 @@ # -# /etc/pacman.conf +# SimulationOS build-host pacman.conf # -# See the pacman.conf(5) manpage for option and repository directives - -# -# GENERAL OPTIONS +# Used by mkarchiso/pacstrap to populate the ISO root. This file is read on the +# BUILD MACHINE, so it must not depend on files that only exist inside the ISO. # +# The [cachyos] repository is declared with an explicit Server= URL rather than +# `Include = /etc/pacman.d/cachyos-mirrorlist` on purpose: the build must not +# silently require a developer-specific /etc/pacman.d file to be present. +# The CachyOS *keyring* is still required on the build host so signatures can be +# verified - scripts/build-iso.sh checks for it and refuses to continue without +# it. Signature verification is never disabled. + [options] -# The following paths are commented out with their default values listed. -# If you wish to use different paths, uncomment and update the paths. -#RootDir = / -#DBPath = /var/lib/pacman/ -#CacheDir = /var/cache/pacman/pkg/ -#LogFile = /var/log/pacman.log -#GPGDir = /etc/pacman.d/gnupg/ -#HookDir = /etc/pacman.d/hooks/ HoldPkg = pacman glibc -#XferCommand = /usr/bin/curl -L -C - -f -o %o %u -#XferCommand = /usr/bin/wget --passive-ftp -c -O %o %u -#CleanMethod = KeepInstalled -Architecture = auto - -# Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup -#IgnorePkg = -#IgnoreGroup = +Architecture = x86_64 -#NoUpgrade = -#NoExtract = - -# Misc options -#UseSyslog Color -#NoProgressBar -# We cannot check disk space from within a chroot environment -#CheckSpace +CheckSpace VerbosePkgLists -DisableDownloadTimeout ParallelDownloads = 10 -ILoveCandy -#DownloadUser = alpm -DisableSandbox +DisableDownloadTimeout -# By default, pacman accepts packages signed by keys that its local keyring -# trusts (see pacman-key and its man page), as well as unsigned packages. SigLevel = Required DatabaseOptional LocalFileSigLevel = Optional -#RemoteFileSigLevel = Required - -# NOTE: You must run `pacman-key --init` before first using pacman; the local -# keyring can then be populated with the keys of all official Arch Linux -# packagers with `pacman-key --populate archlinux`. # # REPOSITORIES -# - can be defined here or included from another file -# - pacman will search repositories in the order defined here -# - local/custom mirrors can be added here or in separate files -# - repositories listed first will take precedence when packages -# have identical names, regardless of version number -# - URLs will have $repo replaced by the name of the current repo -# - URLs will have $arch replaced by the name of the architecture # -# Repository entries are of the format: -# [repo-name] -# Server = ServerName -# Include = IncludePath +# Order matters: Arch repositories are listed FIRST so that a package present in +# both Arch and CachyOS is taken from Arch. SimulationOS deliberately uses +# CachyOS only for what is exclusive to it (linux-cachyos, cachyos-calamares, +# ckbcomp, mkinitcpio-openswap, cachyos-keyring, cachyos-mirrorlist) instead of +# adopting the whole CachyOS-optimised package set. # -# The header [repo-name] is crucial - it must be present and -# uncommented to enable the repo. -# - -# The testing repositories are disabled by default. To enable, uncomment the -# repo name header and Include lines. You can add preferred servers immediately -# after the header, and they will be used before the default mirrors. - -#[core-testing] -#Include = /etc/pacman.d/mirrorlist [core] Include = /etc/pacman.d/mirrorlist -#[extra-testing] -#Include = /etc/pacman.d/mirrorlist - [extra] Include = /etc/pacman.d/mirrorlist -# If you want to run 32 bit applications on your x86_64 system, -# enable the multilib repositories as required here. - -#[multilib-testing] -#Include = /etc/pacman.d/mirrorlist - [multilib] Include = /etc/pacman.d/mirrorlist -# An example of a custom package repository. See the pacman manpage for -# tips on creating your own repositories. -#[custom] -#SigLevel = Optional TrustAll -#Server = file:///home/custompkgs - [cachyos] -Include = /etc/pacman.d/cachyos-mirrorlist +Server = https://mirror.cachyos.org/repo/$arch/$repo +Server = https://cdn.cachyos.org/repo/$arch/$repo diff --git a/profiledef.sh b/profiledef.sh index 4b30203..10ff17c 100644 --- a/profiledef.sh +++ b/profiledef.sh @@ -1,72 +1,55 @@ #!/usr/bin/env bash # shellcheck disable=SC2034 - -iso_name="SimulationOS" -# file_name="${iso_name}-{iso_version}-x86_64.iso" +# +# SimulationOS archiso profile definition. +# +# Only variables that mkarchiso actually consumes are set here. See +# archiso's docs/README.profile.rst for the authoritative list. +# +# Produces: out/simulationos--x86_64.iso +# (mkarchiso builds "${iso_name}-${iso_version}-${arch}.iso") + +iso_name="simulationos" iso_label="SIMOS_$(date --date="@${SOURCE_DATE_EPOCH:-$(date +%s)}" +%Y%m)" iso_publisher="SimulationOS " -iso_application="SimulationOS - Arch-based Rescue and Custom System" +iso_application="SimulationOS Live/Install Medium" iso_version="$(date --date="@${SOURCE_DATE_EPOCH:-$(date +%s)}" +%Y.%m.%d)" install_dir="arch" -buildmodes=('iso') -# systemd-boot -bootmodes=( - 'bios.syslinux.mbr' - 'bios.syslinux.eltorito' - 'uefi-ia32.systemd-boot.esp' - 'uefi-x64.systemd-boot.esp' - 'uefi-ia32.systemd-boot.eltorito' - 'uefi-x64.systemd-boot.eltorito' -) +# buildmodes is intentionally unset: 'iso' is the implicit default. -arch="x86_64" +# Current archiso boot mode names. The pre-0.90 names +# (bios.syslinux.mbr / bios.syslinux.eltorito / uefi-x64.systemd-boot.esp / +# uefi-ia32.systemd-boot.eltorito / ...) are deprecated shims. +# 'uefi.systemd-boot' already covers x64 *and* mixed-mode IA32 on x86_64, +# and it cannot be combined with 'uefi.grub' (mkarchiso rejects that). +bootmodes=('bios.syslinux' + 'uefi.systemd-boot') -pacman_conf="pacman.conf" +arch="x86_64" +# Overridable so the emulated build container can supply a copy with +# DisableSandbox set (pacman's seccomp sandbox returns EINVAL under qemu-user +# emulation). The committed pacman.conf never disables the sandbox, and +# validate-profile.sh enforces that. +pacman_conf="${SIMOS_PACMAN_CONF:-pacman.conf}" airootfs_image_type="squashfs" airootfs_image_tool_options=('-comp' 'xz' '-Xbcj' 'x86' '-b' '1M' '-Xdict-size' '1M') bootstrap_tarball_compression=('zstd' '-c' '-T0' '--auto-threads=logical' '--long' '-19') +# A trailing "/" makes mkarchiso apply ownership/mode recursively. file_permissions=( ["/etc/shadow"]="0:0:400" ["/etc/gshadow"]="0:0:400" ["/root"]="0:0:750" - ["/etc/polkit-1/rules.d"]="0:0:750" - ["/etc/sudoers.d"]="0:0:750" - ["/etc/sudoers.d/g_wheel"]="0:0:440" ["/root/.automated_script.sh"]="0:0:755" ["/root/.gnupg"]="0:0:700" - ["/usr/local/bin/choose-mirror"]="0:0:755" - ["/usr/local/bin/dmcheck"]="0:0:755" - ["/usr/local/bin/calamares-online.sh"]="0:0:755" - ["/usr/local/bin/remove-nvidia"]="0:0:755" - ["/usr/local/bin/removeun"]="0:0:755" - ["/usr/local/bin/removeun-online"]="0:0:755" - ["/usr/local/bin/prepare-live-desktop.sh"]="0:0:755" - ["/usr/local/bin/nvidia-module-loader"]="0:0:755" + ["/etc/sudoers.d"]="0:0:750" + ["/etc/sudoers.d/10-simulationos-live"]="0:0:440" + ["/etc/polkit-1/rules.d"]="0:0:750" + ["/usr/local/bin/livecd-sound"]="0:0:755" + ["/usr/local/bin/simulationos-install"]="0:0:755" + ["/usr/local/bin/simos-screenshot"]="0:0:755" + ["/usr/local/bin/simos-powermenu"]="0:0:755" + ["/usr/local/bin/simos-clipboard"]="0:0:755" + ["/usr/share/simulationos/calamares/scripts/simulationos-deloop"]="0:0:755" ) - -#profiles_description="SimulationOS Arch-based custom live ISO for rescue and simulation purposes" - -#install_dir_disktop="Desktop" - -iso_icon="syslinux/splash.png" - -#additional_packages=( -#"nvim" -#"networkmanager" -#"git" -#"base-devel" -# "linux-headers" -# "btop" -#) - -#kernel_parameters="quite loglevel=3" - -#run_once_custom_airoots_customize() { -# systemctl enable NetworkManager.service -#} - -#run_once_custom_airoots_finallize() { -# rm -rf "${AIROOTFS}/tmp/*" -#} diff --git a/scripts/boot-test.sh b/scripts/boot-test.sh new file mode 100755 index 0000000..26c13cc --- /dev/null +++ b/scripts/boot-test.sh @@ -0,0 +1,135 @@ +#!/usr/bin/env bash +# +# boot-test.sh - L4 automated boot test. +# +# "QEMU started" is not evidence that an OS booted. This boots the ISO +# headlessly with the kernel console on a serial port and waits for proof that +# the system actually reached a usable state, then reports which checks passed. +# +# It never waits forever: every run ends in PASS, FAIL or TIMEOUT. +# +set -uo pipefail + +REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +OUT="${SIMOS_OUT_DIR:-$REPO/out}" +ISO="${1:-$(ls -1t "$OUT"/simulationos-*.iso 2>/dev/null | head -1)}" +FIRMWARE="${SIMOS_BOOT_TEST_FIRMWARE:-uefi}" +TIMEOUT="${SIMOS_BOOT_TEST_TIMEOUT:-600}" +RAM="${SIMOS_BOOT_TEST_RAM:-3072}" +LOG="$OUT/boot-test-${FIRMWARE}.log" + +red() { printf '\033[31m%s\033[0m\n' "$*" >&2; } +green() { printf '\033[32m%s\033[0m\n' "$*"; } +info() { printf '\033[36m==>\033[0m %s\n' "$*"; } + +[ -n "$ISO" ] && [ -f "$ISO" ] || { red "no ISO found in $OUT"; exit 1; } +command -v qemu-system-x86_64 >/dev/null || { red "qemu-system-x86_64 not installed"; exit 1; } + +mkdir -p "$OUT" +[ "${SIMOS_BOOT_ANALYZE_ONLY:-0}" = "1" ] || : > "$LOG" + +# shellcheck disable=SC2054 # commas are part of QEMU option values +QEMU=(qemu-system-x86_64 + -machine "q35,accel=${SIMOS_QEMU_ACCEL:-kvm:tcg}" + -cpu max -smp 2 -m "$RAM" + -display none -vga std + -serial "file:$LOG" + -device virtio-net-pci,netdev=n0 -netdev user,id=n0 + -drive "file=$ISO,media=cdrom,readonly=on" -boot order=d + -no-reboot) + +if [ "$FIRMWARE" = "uefi" ]; then + CODE="" + for c in /opt/homebrew/share/qemu/edk2-x86_64-code.fd \ + /usr/local/share/qemu/edk2-x86_64-code.fd \ + /usr/share/edk2/x64/OVMF_CODE.4m.fd /usr/share/edk2/x64/OVMF_CODE.fd \ + /usr/share/edk2-ovmf/x64/OVMF_CODE.fd /usr/share/OVMF/OVMF_CODE_4M.fd; do + [ -f "$c" ] && { CODE="$c"; break; } + done + [ -n "$CODE" ] || { red "OVMF not found; install edk2-ovmf or use SIMOS_BOOT_TEST_FIRMWARE=bios"; exit 1; } + VARS_SRC="" + for v in /opt/homebrew/share/qemu/edk2-i386-vars.fd \ + /usr/local/share/qemu/edk2-i386-vars.fd \ + /usr/share/edk2/x64/OVMF_VARS.4m.fd /usr/share/edk2/x64/OVMF_VARS.fd \ + /usr/share/edk2-ovmf/x64/OVMF_VARS.fd /usr/share/OVMF/OVMF_VARS_4M.fd; do + [ -f "$v" ] && { VARS_SRC="$v"; break; } + done + VARS="$OUT/OVMF_VARS.boot-test.fd"; cp -f "$VARS_SRC" "$VARS" + QEMU+=(-drive "if=pflash,format=raw,unit=0,readonly=on,file=$CODE" + -drive "if=pflash,format=raw,unit=1,file=$VARS") +fi + +# Markers proving progressively deeper boot stages. Crucially this also +# watches for failure signatures, so a kernel panic is reported rather than +# looking identical to "still booting". +SUCCESS='Reached target Graphical Interface|reached target graphical|login:|servicename=display-manager' +FAILURE='Kernel panic|Unable to mount root|end Kernel panic|You are in emergency mode|Failed to start Light Display Manager|Entering emergency mode' + +if [ "${SIMOS_BOOT_ANALYZE_ONLY:-0}" = "1" ]; then + info "Analysing the existing log $LOG without booting" + QPID=0 +else +info "Booting $(basename "$ISO") headlessly ($FIRMWARE, timeout ${TIMEOUT}s)" +"${QEMU[@]}" & +QPID=$! +# shellcheck disable=SC2064 +trap "kill $QPID 2>/dev/null" EXIT + + +fi + +deadline=$(( $(date +%s) + TIMEOUT )) +if [ "${SIMOS_BOOT_ANALYZE_ONLY:-0}" = "1" ]; then deadline=0; fi +result="TIMEOUT" +if [ "${SIMOS_BOOT_ANALYZE_ONLY:-0}" = "1" ]; then + grep -qE "$FAILURE" "$LOG" 2>/dev/null && result="FAIL" + grep -qE "$SUCCESS" "$LOG" 2>/dev/null && result="PASS" +fi +while [ "$(date +%s)" -lt "$deadline" ]; do + [ "$QPID" -eq 0 ] && break + kill -0 "$QPID" 2>/dev/null || { result="QEMU_EXITED"; break; } + if grep -qE "$FAILURE" "$LOG" 2>/dev/null; then result="FAIL"; break; fi + if grep -qE "$SUCCESS" "$LOG" 2>/dev/null; then result="PASS"; break; fi + sleep 3 +done +[ "$QPID" -ne 0 ] && { kill "$QPID" 2>/dev/null; wait "$QPID" 2>/dev/null; } + +printf '\n== boot stages observed\n' +# Two kinds of stage: ones whose absence is a real problem, and ones that are +# simply not visible on the serial console because tty0 is the primary console +# (systemd sends its status there). Reporting the latter as MISS reads as a +# failure when the boot is healthy, so they are labelled distinctly. +check() { + if grep -qE "$2" "$LOG" 2>/dev/null; then green " ok $1"; else red " MISSING $1"; fi +} +info_check() { + if grep -qE "$2" "$LOG" 2>/dev/null; then + green " ok $1" + else + printf ' n/a %s (not emitted to serial; tty0 is the primary console)\n' "$1" + fi +} +info_check "kernel started" 'Linux version' +check "linux-cachyos kernel" 'linux-cachyos|cachyos' +info_check "archiso initramfs ran" 'archiso|Mounting .*airootfs|/run/archiso' +info_check "systemd started" 'systemd\[1\]' +info_check "reached multi-user" 'Reached target Multi-User|reached target multi-user' +check "getty/login prompt reached" 'login:' +check "SimulationOS branding shown" 'SimulationOS' +info_check "reached graphical target" 'Reached target Graphical Interface|servicename=display-manager|servicename=sddm' +if grep -q 'Kernel panic' "$LOG" 2>/dev/null; then + red " MISS no kernel panic" +else + green " ok no kernel panic" +fi + +printf '\n' +case "$result" in + PASS) green "BOOT TEST PASSED ($FIRMWARE) - log: $LOG"; exit 0 ;; + FAIL) red "BOOT TEST FAILED ($FIRMWARE) - failure signature in $LOG" + grep -nE "$FAILURE" "$LOG" | head -5; exit 1 ;; + QEMU_EXITED) red "BOOT TEST FAILED: QEMU exited before reaching a target - log: $LOG" + tail -20 "$LOG"; exit 1 ;; + *) red "BOOT TEST TIMEOUT after ${TIMEOUT}s ($FIRMWARE) - log: $LOG" + tail -20 "$LOG"; exit 1 ;; +esac diff --git a/scripts/build-iso.sh b/scripts/build-iso.sh new file mode 100755 index 0000000..dcf9bf8 --- /dev/null +++ b/scripts/build-iso.sh @@ -0,0 +1,178 @@ +#!/usr/bin/env bash +# +# build-iso.sh - build the SimulationOS ISO with mkarchiso. +# +# Refuses to run in an environment that cannot produce a correct x86_64 ISO +# rather than emitting a broken or wrong-architecture image. +# +set -euo pipefail + +REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +WORK="${SIMOS_WORK_DIR:-$REPO/work}" +OUT="${SIMOS_OUT_DIR:-$REPO/out}" + +# CachyOS signing key, per CachyOS' own cachyos-repo.sh. +CACHYOS_KEY="F3B607488DB35A47" +CACHYOS_MIRROR="https://mirror.cachyos.org/repo/x86_64/cachyos" + +red() { printf '\033[31m%s\033[0m\n' "$*" >&2; } +green() { printf '\033[32m%s\033[0m\n' "$*"; } +info() { printf '\033[36m==>\033[0m %s\n' "$*"; } +die() { red "ERROR: $*"; exit 1; } + +# ------------------------------------------------------------------ 1. host +info "Checking build environment" + +[ "$(uname -s)" = "Linux" ] || die "mkarchiso only runs on Linux. This host is $(uname -s). + Build SimulationOS on an Arch Linux x86_64 machine, VM, or container. + See README.md -> Building for a container recipe." + +if [ "$(uname -m)" != "x86_64" ]; then + die "This host is $(uname -m), but SimulationOS targets x86_64. + Building here would produce packages for the wrong architecture. + Use an x86_64 Arch host or an x86_64 container." +fi + +[ "$(id -u)" -eq 0 ] || die "mkarchiso must run as root. Try: sudo $0 $*" + +command -v pacman >/dev/null || die "pacman not found: this is not an Arch-based host." +command -v mkarchiso >/dev/null || die "mkarchiso not found. Install it with: pacman -S archiso" + +# --------------------------------------------------- 2. CachyOS prerequisites +info "Checking CachyOS repository prerequisites" + +if ! pacman -Q cachyos-keyring >/dev/null 2>&1; then + red "The cachyos-keyring package is not installed on this build host." + red "" + red "SimulationOS installs linux-cachyos, cachyos-calamares, ckbcomp and" + red "mkinitcpio-openswap from the CachyOS repository. pacstrap verifies those" + red "signatures against the BUILD HOST keyring, so the key must be trusted here." + red "Package signature verification is never disabled to work around this." + red "" + red "Provision it with:" + red " pacman-key --recv-keys $CACHYOS_KEY --keyserver keyserver.ubuntu.com" + red " pacman-key --lsign-key $CACHYOS_KEY" + red " pacman -Sy --config $REPO/pacman.conf cachyos-keyring cachyos-mirrorlist" + red "" + red "(Installing through the profile's own pacman.conf avoids a hardcoded" + red " package-version URL, which goes stale every time CachyOS rebuilds" + red " the keyring.)" + exit 1 +fi + +if ! pacman-key --list-keys "$CACHYOS_KEY" >/dev/null 2>&1; then + die "cachyos-keyring is installed but key $CACHYOS_KEY is not in the pacman keyring. + Run: pacman-key --populate cachyos" +fi +green " CachyOS keyring present and key $CACHYOS_KEY is trusted" + +# The profile's pacman.conf pins explicit CachyOS Server= URLs, so no +# /etc/pacman.d/cachyos-mirrorlist is needed on the host. Confirm the repo +# actually resolves before spending an hour on a build. +info "Verifying the CachyOS repository resolves" +if ! pacman -Sp --config "$REPO/pacman.conf" linux-cachyos >/dev/null 2>&1; then + die "Cannot resolve 'linux-cachyos' through $REPO/pacman.conf. + Check network access to $CACHYOS_MIRROR and that the [cachyos] section is intact." +fi +green " linux-cachyos resolves: $(pacman -Sp --config "$REPO/pacman.conf" linux-cachyos 2>/dev/null | head -1)" + +# ------------------------------------------------------------ 3. static checks +info "Running profile validation" +if ! "$REPO/scripts/validate-profile.sh"; then + die "validate-profile.sh failed. Fix the errors above before building." +fi + +# ------------------------------------------------------------------ 4. workdir +if [ -d "$WORK" ]; then + if [ "${SIMOS_REUSE_WORK:-0}" = "1" ]; then + info "Reusing existing work directory $WORK (SIMOS_REUSE_WORK=1)" + else + info "Clearing stale work directory $WORK" + "$REPO/scripts/clean-build.sh" --keep-iso + fi +fi +mkdir -p -- "$WORK" "$OUT" + +# A case-insensitive work directory silently breaks the build ~40 minutes in: +# xorg-server ships BOTH /usr/lib/Xorg (a file) and /usr/lib/xorg/ (a +# directory), and pacman aborts with +# error: extract: not overwriting dir with file .../usr/lib/Xorg +# This bites when the work directory is a bind mount from macOS (APFS) or a +# Windows filesystem. Fail immediately, with the fix, instead. +_case_probe="$WORK/.simos-case-probe" +mkdir -p "$_case_probe/xorg" +if [ -e "$_case_probe/XORG" ]; then + rm -rf -- "$_case_probe" + die "the work directory is on a CASE-INSENSITIVE filesystem: $WORK + Packages such as xorg-server ship /usr/lib/Xorg and /usr/lib/xorg/, + which collide there and abort pacstrap partway through the build. + Point SIMOS_WORK_DIR at a case-sensitive filesystem, e.g.: + SIMOS_WORK_DIR=/var/tmp/simulationos-work $0 + (./build.sh already does this for containerised builds.)" +fi +rm -rf -- "$_case_probe" +green " work directory is case-sensitive" + +# -------------------------------------------------------------------- 5. build +info "Running mkarchiso (this takes a while and needs ~20 GB free)" +BUILD_LOG="$OUT/build.log" +BUILD_START="$(date -u +%s)" +set -o pipefail +mkarchiso -v -w "$WORK" -o "$OUT" "$REPO" 2>&1 | tee "$BUILD_LOG" +BUILD_END="$(date -u +%s)" + +# ------------------------------------------------------------- 6/7. artifact +ISO="$(ls -1t "$OUT"/simulationos-*.iso 2>/dev/null | head -1)" +[ -n "$ISO" ] || die "mkarchiso finished but no ISO was produced in $OUT" + +info "Generating SHA256 checksum" +( cd "$OUT" && sha256sum "$(basename "$ISO")" > "$(basename "$ISO").sha256" ) + +# Derived from the produced filename (iso_name-iso_version-arch.iso), which is +# ground truth, instead of re-sourcing profiledef.sh. +ISO_BASE="$(basename "$ISO" .iso)" +ISO_ARCH="${ISO_BASE##*-}" +ISO_VERSION="${ISO_BASE%-*}"; ISO_VERSION="${ISO_VERSION##*-}" + +info "Writing build-info.json" +# Everything a release engineer needs to answer "which commit produced this +# exact file, with which tools". +cat > "$OUT/build-info.json" </dev/null || stat -f%z "$ISO"), + "iso_version": "$ISO_VERSION", + "target_arch": "$ISO_ARCH", + "git_commit": "$(git -C "$REPO" rev-parse HEAD 2>/dev/null || echo unknown)", + "git_branch": "$(git -C "$REPO" rev-parse --abbrev-ref HEAD 2>/dev/null || echo unknown)", + "git_dirty": $(test -n "$(git -C "$REPO" status --porcelain 2>/dev/null)" && echo true || echo false), + "archiso_version": "$(pacman -Q archiso 2>/dev/null | awk '{print $2}' || echo unknown)", + "pacman_version": "$(pacman -Q pacman 2>/dev/null | awk '{print $2}' || echo unknown)", + "build_date_utc": "$(date -u +%Y-%m-%dT%H:%M:%SZ)", + "build_seconds": $(( BUILD_END - BUILD_START )), + "builder_host": "$(uname -srm)" +} +JSON +if command -v python3 >/dev/null 2>&1; then + python3 -c "import json;json.load(open('$OUT/build-info.json'))" 2>/dev/null \ + && green " build-info.json is valid JSON" \ + || die "build-info.json is not valid JSON" +elif command -v jq >/dev/null 2>&1; then + jq -e . "$OUT/build-info.json" >/dev/null 2>&1 \ + && green " build-info.json is valid JSON" \ + || die "build-info.json is not valid JSON" +else + info " (no python3 or jq in the builder; skipping JSON validation)" +fi + +green "" +green "Build complete" +green " ISO: $ISO" +green " Size: $(du -h "$ISO" | cut -f1)" +green " SHA256: $(cut -d' ' -f1 < "$ISO.sha256")" +green " Checksum: $ISO.sha256" +green " Metadata: $OUT/build-info.json" +green " Log: $BUILD_LOG" +green "" +green "Boot it with: ./scripts/test-iso.sh \"$ISO\"" diff --git a/scripts/clean-build.sh b/scripts/clean-build.sh new file mode 100755 index 0000000..35775d0 --- /dev/null +++ b/scripts/clean-build.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +# +# clean-build.sh - remove SimulationOS build artefacts. +# +# Only ever touches ./work and ./out inside the repository; it refuses to +# delete anything outside it. +# +set -euo pipefail + +REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +WORK="${SIMOS_WORK_DIR:-$REPO/work}" +OUT="${SIMOS_OUT_DIR:-$REPO/out}" + +KEEP_ISO=0 +[ "${1:-}" = "--keep-iso" ] && KEEP_ISO=1 + +info() { printf '\033[36m==>\033[0m %s\n' "$*"; } + +# Guard rail. Paths inside the repository are always fine. Paths outside it +# are allowed only when they are explicitly chosen build directories - +# containerised builds put the work directory on a case-sensitive filesystem +# such as /var/tmp - and never when they are a system directory. +for target in "$WORK" "$OUT"; do + case "$target" in + "$REPO"/*) + ;; + /var/tmp/*|/tmp/*) + ;; + ""|/|/usr|/usr/*|/etc|/etc/*|/home|/home/*|/var|/var/*|/opt|/opt/*|/boot|/boot/*) + printf 'refusing to delete %s: system directory\n' "$target" >&2; exit 1 ;; + *) + printf 'refusing to delete %s: outside the repository and not a build directory\n' "$target" >&2 + printf 'set SIMOS_WORK_DIR/SIMOS_OUT_DIR under the repo or /var/tmp\n' >&2 + exit 1 ;; + esac +done + +# mkarchiso leaves bind mounts behind if a build was interrupted; unmount them +# before deleting, otherwise the delete can reach into a mounted filesystem. +if [ -d "$WORK" ] && command -v findmnt >/dev/null 2>&1; then + findmnt -rno TARGET --submounts "$WORK" 2>/dev/null | sort -r | while read -r mp; do + info "Unmounting leftover mount $mp" + umount -l -- "$mp" 2>/dev/null || true + done +fi + +if [ -d "$WORK" ]; then + info "Removing work directory $WORK ($(du -sh "$WORK" 2>/dev/null | cut -f1))" + rm -rf -- "$WORK" +else + info "No work directory to remove" +fi + +if [ "$KEEP_ISO" -eq 1 ]; then + info "Keeping $OUT (--keep-iso)" +elif [ -d "$OUT" ]; then + info "Removing output directory $OUT" + rm -rf -- "$OUT" +else + info "No output directory to remove" +fi + +info "Clean" diff --git a/scripts/deloop-test.sh b/scripts/deloop-test.sh new file mode 100755 index 0000000..344f920 --- /dev/null +++ b/scripts/deloop-test.sh @@ -0,0 +1,109 @@ +#!/usr/bin/env bash +# +# deloop-test.sh - verify the de-live contract. +# +# simulationos-deloop turns a verbatim copy of the live filesystem into a safe +# installed system. Because the offline installer uses unpackfs, every live +# concession (empty root password, NOPASSWD sudo, permissive polkit, SDDM +# autologin, the archiso initramfs hook) is present on the target until deloop +# removes it. +# +# This extracts the SquashFS from the real ISO, runs deloop inside it exactly +# as Calamares would, and asserts the security properties of the result. It +# covers the same gates as the post-install checks without needing to drive +# the graphical installer. +# +set -uo pipefail + +REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +OUT="${SIMOS_OUT_DIR:-$REPO/out}" +ISO="${1:-$(ls -1t "$OUT"/simulationos-*.iso 2>/dev/null | head -1)}" +WORK="${SIMOS_DELOOP_WORK:-/var/tmp/simos-deloop}" + +red() { printf '\033[31m%s\033[0m\n' "$*" >&2; } +green() { printf '\033[32m%s\033[0m\n' "$*"; } +info() { printf '\033[36m==>\033[0m %s\n' "$*"; } + +[ -n "$ISO" ] && [ -f "$ISO" ] || { red "no ISO found in $OUT"; exit 1; } +[ "$(id -u)" -eq 0 ] || { red "must run as root (chroot); try: sudo $0"; exit 1; } +command -v unsquashfs >/dev/null || { red "unsquashfs not found (install squashfs-tools)"; exit 1; } +command -v bsdtar >/dev/null || { red "bsdtar not found (install libarchive-tools)"; exit 1; } + +# Guard rail: this script deletes its work directory, so it must be a scratch +# path and nothing else. +case "$WORK" in + /var/tmp/*|/tmp/*) ;; + *) red "refusing to use work directory $WORK (must be under /var/tmp or /tmp)"; exit 1 ;; +esac + +rm -rf -- "$WORK" +mkdir -p "$WORK/root" + +info "Extracting the SquashFS from $(basename "$ISO")" +IDIR="$(sed -n 's/^install_dir="\(.*\)"/\1/p' "$REPO/profiledef.sh" | head -1)" +IARCH="$(sed -n 's/^arch="\(.*\)"/\1/p' "$REPO/profiledef.sh" | head -1)" +bsdtar -xOf "$ISO" "${IDIR}/${IARCH}/airootfs.sfs" > "$WORK/airootfs.sfs" \ + || { red "could not extract airootfs.sfs from the ISO"; exit 1; } +unsquashfs -f -d "$WORK/root" "$WORK/airootfs.sfs" >/dev/null \ + || { red "unsquashfs failed"; exit 1; } +green " rootfs extracted to $WORK/root" + +R="$WORK/root" +DELOOP=/usr/share/simulationos/calamares/scripts/simulationos-deloop +[ -x "$R$DELOOP" ] || { red "deloop script missing from the ISO: $DELOOP"; exit 1; } + +# --------------------------------------------------------------- preconditions +printf '\n== live-medium preconditions (what deloop must remove)\n' +pre_bad=0 +check_pre() { if eval "$2"; then green " present $1"; else red " ABSENT $1 (precondition not met)"; pre_bad=1; fi; } +check_pre "SDDM live autologin" "[ -f '$R/etc/sddm.conf.d/20-simulationos-live-autologin.conf' ]" +check_pre "NOPASSWD sudoers" "[ -f '$R/etc/sudoers.d/10-simulationos-live' ]" +check_pre "permissive polkit rule" "[ -f '$R/etc/polkit-1/rules.d/49-simulationos-live-nopasswd.rules' ]" +check_pre "archiso initramfs hook" "[ -f '$R/etc/mkinitcpio.conf.d/archiso.conf' ]" +check_pre "root has empty password" "grep -q '^root::' '$R/etc/shadow'" +check_pre "liveuser account" "grep -q '^liveuser:' '$R/etc/passwd'" +check_pre "installer launcher" "[ -x '$R/usr/local/bin/simulationos-install' ]" +[ "$pre_bad" -eq 0 ] || { red "extracted rootfs is not in the expected live state"; exit 1; } + +# ----------------------------------------------------------- run the transform +info "Running simulationos-deloop inside the chroot (as Calamares does)" +for m in proc sys dev; do mount --rbind "/$m" "$R/$m" 2>/dev/null; done +# Calamares removes the live account first (removeuser module); mirror that. +chroot "$R" /usr/bin/userdel -r liveuser >/dev/null 2>&1 || true +chroot "$R" "$DELOOP" 2>&1 | sed 's/^/ /' +DELOOP_RC=${PIPESTATUS[0]} +for m in dev sys proc; do umount -R "$R/$m" 2>/dev/null; done +[ "$DELOOP_RC" -eq 0 ] || { red "deloop exited $DELOOP_RC"; exit 1; } + +# ------------------------------------------------------------------ acceptance +printf '\n== installed-system acceptance gates\n' +ERRORS=0 +gate() { if eval "$2"; then green " ok $1"; else red " FAILED $1"; ERRORS=$((ERRORS+1)); fi; } + +gate "liveuser removed from /etc/passwd" "! grep -q '^liveuser:' '$R/etc/passwd'" +gate "/home/liveuser removed" "[ ! -d '$R/home/liveuser' ]" +gate "SDDM live autologin removed" "[ ! -f '$R/etc/sddm.conf.d/20-simulationos-live-autologin.conf' ]" +gate "tty1 autologin drop-in removed" "[ ! -f '$R/etc/systemd/system/getty@tty1.service.d/autologin.conf' ]" +gate "NOPASSWD sudoers removed" "[ ! -f '$R/etc/sudoers.d/10-simulationos-live' ]" +gate "password-prompting wheel rule added" "grep -q '^%wheel ALL=(ALL:ALL) ALL' '$R/etc/sudoers.d/10-simulationos-wheel'" +gate "no NOPASSWD rule left in sudoers.d" "! grep -rq 'NOPASSWD' '$R/etc/sudoers.d/'" +gate "permissive polkit rule removed" "[ ! -f '$R/etc/polkit-1/rules.d/49-simulationos-live-nopasswd.rules' ]" +gate "root account locked" "grep -qE '^root:[!*]' '$R/etc/shadow'" +gate "root no longer has an empty password" "! grep -q '^root::' '$R/etc/shadow'" +gate "archiso initramfs hook removed" "[ ! -f '$R/etc/mkinitcpio.conf.d/archiso.conf' ]" +gate "no archiso hook in mkinitcpio config" "! grep -rqs 'archiso' '$R/etc/mkinitcpio.conf.d/' '$R/etc/mkinitcpio.conf'" +gate "archiso live units removed" "[ ! -f '$R/etc/systemd/system/livecd-talk.service' ] && [ ! -f '$R/etc/systemd/system/pacman-init.service' ]" +gate "installer launcher removed" "[ ! -e '$R/usr/local/bin/simulationos-install' ]" +gate "installer desktop entry removed" "[ ! -e '$R/usr/share/applications/simulationos-install.desktop' ]" +gate "display-manager still enabled" "[ -L '$R/etc/systemd/system/display-manager.service' ]" +gate "default.target still graphical" "readlink '$R/etc/systemd/system/default.target' | grep -q graphical" +gate "SimulationOS identity intact" "grep -q 'ID=simulationos' '$R/etc/os-release'" +gate "desktop skel intact for new users" "[ -f '$R/etc/skel/.config/hypr/hyprland.conf' ]" + +printf '\n' +rm -rf -- "$WORK" +if [ "$ERRORS" -gt 0 ]; then + red "DELOOP CONTRACT FAILED: $ERRORS gate(s)" + exit 1 +fi +green "DELOOP CONTRACT PASSED: the de-live transformation is correct" diff --git a/scripts/inspect-iso.sh b/scripts/inspect-iso.sh new file mode 100755 index 0000000..8e44fe9 --- /dev/null +++ b/scripts/inspect-iso.sh @@ -0,0 +1,116 @@ +#!/usr/bin/env bash +# +# inspect-iso.sh - L3 artefact inspection. +# +# A zero exit code from mkarchiso is not evidence of a usable ISO. This +# verifies the image actually contains what SimulationOS is supposed to ship, +# and that the kernel names inside it match the profile. +# +set -uo pipefail + +REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +OUT="${SIMOS_OUT_DIR:-$REPO/out}" +ISO="${1:-$(ls -1t "$OUT"/simulationos-*.iso 2>/dev/null | head -1)}" + +ERRORS=0 +red() { printf '\033[31m%s\033[0m\n' "$*" >&2; } +green() { printf '\033[32m%s\033[0m\n' "$*"; } +err() { ERRORS=$((ERRORS+1)); red " FAIL $*"; } +ok() { green " ok $*"; } + +[ -n "$ISO" ] && [ -f "$ISO" ] || { red "no ISO found in $OUT"; exit 1; } +printf '== inspecting %s\n' "$(basename "$ISO")" + +# ---------------------------------------------------------------- size / name +SIZE=$(stat -c%s "$ISO" 2>/dev/null || stat -f%z "$ISO") +[ "$SIZE" -gt 0 ] || err "ISO is empty" +[ "$SIZE" -gt 524288000 ] || err "ISO is only $((SIZE/1024/1024)) MB; a Hyprland + installer image should be well over 500 MB" +ok "size $((SIZE/1024/1024)) MB" + +case "$(basename "$ISO")" in + simulationos-*-x86_64.iso) ok "filename matches simulationos--x86_64.iso" ;; + *) err "unexpected ISO filename: $(basename "$ISO")" ;; +esac + +# ------------------------------------------------------------------ contents +if ! command -v bsdtar >/dev/null 2>&1; then + red "bsdtar not available; cannot inspect ISO contents" + exit 1 +fi +LIST="$(bsdtar -tf "$ISO" 2>/dev/null)" +[ -n "$LIST" ] || { err "could not read the ISO filesystem"; exit 1; } + +# Derive the expected kernel from the profile, so this test cannot drift. +KPKG="$(grep -vE '^[[:space:]]*(#|$)' "$REPO/packages.x86_64" \ + | grep -E '^linux(-[a-z0-9]+)*$' \ + | grep -vE '^linux-(firmware|api-headers|atm)' | grep -vE -- '-headers$' | tail -1)" +IDIR="$(sed -n 's/^install_dir="\(.*\)"/\1/p' "$REPO/profiledef.sh" | head -1)" +IARCH="$(sed -n 's/^arch="\(.*\)"/\1/p' "$REPO/profiledef.sh" | head -1)" + +expect() { + if printf '%s\n' "$LIST" | grep -qx -- "$1"; then ok "$1"; else err "missing from ISO: $1"; fi +} +expect "${IDIR}/boot/${IARCH}/vmlinuz-${KPKG}" +expect "${IDIR}/boot/${IARCH}/initramfs-${KPKG}.img" +expect "${IDIR}/${IARCH}/airootfs.sfs" +expect "${IDIR}/${IARCH}/airootfs.sha512" + +# The installer's unpackfs source must exist at the path we configured. +SFS_EXPECT="/run/archiso/bootmnt/${IDIR}/${IARCH}/airootfs.sfs" +grep -q "$SFS_EXPECT" "$REPO/airootfs/usr/share/simulationos/calamares/modules/unpackfs.conf" \ + && ok "unpackfs source matches the ISO layout" \ + || err "unpackfs.conf does not point at $SFS_EXPECT" + +# Boot loader payloads for the declared bootmodes. +if grep -q "'bios.syslinux'" "$REPO/profiledef.sh"; then + # mkarchiso places syslinux under boot/syslinux/, not /syslinux/. + expect "boot/syslinux/isolinux.bin" + expect "boot/syslinux/archiso_sys-linux.cfg" +fi +if grep -q "'uefi.systemd-boot'" "$REPO/profiledef.sh"; then + printf '%s\n' "$LIST" | grep -qi '^EFI/BOOT/BOOTX64.EFI$' && ok "EFI/BOOT/BOOTX64.EFI present (UEFI)" \ + || err "uefi.systemd-boot declared but EFI/BOOT/BOOTX64.EFI is missing" + printf '%s\n' "$LIST" | grep -q '^loader/entries/01-simulationos-linux.conf$' \ + && ok "systemd-boot default entry present" \ + || err "loader/entries/01-simulationos-linux.conf missing" +fi + +# The boot menus a user actually sees must say SimulationOS. Read them out of +# the built ISO rather than trusting the source tree. +TMPD="$(mktemp -d)" +for entry in "boot/syslinux/archiso_sys-linux.cfg" "loader/entries/01-simulationos-linux.conf"; do + if printf '%s\n' "$LIST" | grep -qx -- "$entry"; then + if bsdtar -xOf "$ISO" "$entry" >"$TMPD/e" 2>/dev/null && [ -s "$TMPD/e" ]; then + grep -qi 'SimulationOS' "$TMPD/e" \ + && ok "boot menu is branded SimulationOS ($entry)" \ + || err "$entry contains no SimulationOS branding" + grep -qi 'Arch Linux install medium' "$TMPD/e" \ + && err "$entry still carries the upstream Arch label" + # The kernel the menu points at must be the one in the ISO. + if grep -qiE 'vmlinuz-[a-z0-9.-]+' "$TMPD/e"; then + grep -qi "vmlinuz-${KPKG}" "$TMPD/e" \ + && ok "$entry references vmlinuz-${KPKG}" \ + || err "$entry references a kernel other than ${KPKG}" + fi + fi + fi +done +rm -rf -- "$TMPD" + +# ------------------------------------------------------------------ checksum +if [ -f "$ISO.sha256" ]; then + if (cd "$(dirname "$ISO")" && sha256sum -c "$(basename "$ISO").sha256" >/dev/null 2>&1); then + ok "sha256 matches" + else + err "sha256 mismatch" + fi +else + err "no .sha256 beside the ISO" +fi + +printf '\n' +if [ "$ERRORS" -gt 0 ]; then + red "ISO inspection FAILED with $ERRORS problem(s)" + exit 1 +fi +green "ISO inspection PASSED" diff --git a/scripts/live-health.sh b/scripts/live-health.sh new file mode 100755 index 0000000..d9feb77 --- /dev/null +++ b/scripts/live-health.sh @@ -0,0 +1,198 @@ +#!/usr/bin/env bash +# +# live-health.sh - L4b live-system acceptance. +# +# Boots the ISO, logs in on the serial console and runs real health checks +# INSIDE the guest: graphical.target, SDDM, the liveuser session, Hyprland, +# NetworkManager, PipeWire, portals and polkit. +# +# Package presence is not acceptance; this asserts on running state. +# +# The live medium ships root with an empty password (standard archiso), which +# is what makes an unattended serial login possible. That is a property of the +# live medium only - simulationos-deloop locks root on the installed system. +# +set -uo pipefail + +REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +OUT="${SIMOS_OUT_DIR:-$REPO/out}" +ISO="${1:-$(ls -1t "$OUT"/simulationos-*.iso 2>/dev/null | head -1)}" +TIMEOUT="${SIMOS_LIVE_TIMEOUT:-1800}" +RAM="${SIMOS_LIVE_RAM:-4096}" +ACCEL="${SIMOS_QEMU_ACCEL:-kvm:tcg}" +LOG="$OUT/live-health.log" +PIPE="${TMPDIR:-/tmp}/simos-serial" + +red() { printf '\033[31m%s\033[0m\n' "$*" >&2; } +green() { printf '\033[32m%s\033[0m\n' "$*"; } +info() { printf '\033[36m==>\033[0m %s\n' "$*"; } + +[ -n "$ISO" ] && [ -f "$ISO" ] || { red "no ISO found in $OUT"; exit 1; } +command -v qemu-system-x86_64 >/dev/null || { red "qemu-system-x86_64 not installed"; exit 1; } + +rm -f "$PIPE.in" "$PIPE.out" +mkfifo "$PIPE.in" "$PIPE.out" +: > "$LOG" + +OVMF_CODE="" +for c in /usr/share/OVMF/OVMF_CODE_4M.fd /usr/share/OVMF/OVMF_CODE.fd \ + /usr/share/edk2/x64/OVMF_CODE.4m.fd /usr/share/edk2-ovmf/x64/OVMF_CODE.fd \ + /opt/homebrew/share/qemu/edk2-x86_64-code.fd; do + [ -f "$c" ] && { OVMF_CODE="$c"; break; } +done +OVMF_VARS_SRC="" +for v in /usr/share/OVMF/OVMF_VARS_4M.fd /usr/share/OVMF/OVMF_VARS.fd \ + /usr/share/edk2/x64/OVMF_VARS.4m.fd /usr/share/edk2-ovmf/x64/OVMF_VARS.fd \ + /opt/homebrew/share/qemu/edk2-i386-vars.fd; do + [ -f "$v" ] && { OVMF_VARS_SRC="$v"; break; } +done +[ -n "$OVMF_CODE" ] && [ -n "$OVMF_VARS_SRC" ] || { red "OVMF firmware not found"; exit 1; } +VARS="$OUT/OVMF_VARS.live-health.fd"; cp -f "$OVMF_VARS_SRC" "$VARS" + +info "Booting $(basename "$ISO") for live health checks (timeout ${TIMEOUT}s)" +# shellcheck disable=SC2054 # commas are part of QEMU option values +qemu-system-x86_64 \ + -machine "q35,accel=$ACCEL" -cpu max -smp 2 -m "$RAM" \ + -display none -vga std \ + -drive "if=pflash,format=raw,unit=0,readonly=on,file=$OVMF_CODE" \ + -drive "if=pflash,format=raw,unit=1,file=$VARS" \ + -serial "pipe:$PIPE" \ + -device virtio-net-pci,netdev=n0 -netdev user,id=n0 \ + -audiodev none,id=nosnd -device intel-hda -device hda-duplex,audiodev=nosnd \ + -drive "file=$ISO,media=cdrom,readonly=on" -boot order=d -no-reboot & +QPID=$! +# shellcheck disable=SC2064 +trap "kill $QPID 2>/dev/null; rm -f '$PIPE.in' '$PIPE.out'" EXIT + +# Stream the guest's serial output into the log. +cat "$PIPE.out" >>"$LOG" & +CATPID=$! +exec 3>"$PIPE.in" +say() { printf '%s\n' "$1" >&3; } + +# Strip NULs, CSI colour codes, OSC sequences (systemd shell integration) +# and turn CR into LF so line anchors mean what they say. +clean_log() { + tr -d '\000' < "$LOG" \ + | sed -e 's/\x1b\][^\x07]*\x07//g' \ + -e 's/\x1b\][^\x1b]*\x1b\\//g' \ + -e 's/\x1b\[[0-9;?=]*[a-zA-Z]//g' \ + -e 's/\r/\n/g' \ + | awk '{gsub(/##BEGIN /,"\n##BEGIN "); gsub(/##END /,"\n##END "); print}' +} + +wait_for() { # pattern, seconds + local deadline=$(( $(date +%s) + $2 )) + while [ "$(date +%s)" -lt "$deadline" ]; do + kill -0 "$QPID" 2>/dev/null || return 2 + clean_log | grep -aqE "$1" && return 0 + sleep 3 + done + return 1 +} + +info "Waiting for the login prompt" +wait_for 'simulationos login:|login:' "$TIMEOUT"; rc=$? +if [ "$rc" -eq 2 ]; then + red "QEMU exited before the guest reached a login prompt." + red "This is usually a QEMU invocation problem, not a SimulationOS problem." + red "Serial output captured so far:"; tail -30 "$LOG" + exit 1 +elif [ "$rc" -ne 0 ]; then + red "timed out after ${TIMEOUT}s waiting for a login prompt" + red "(hosted runners have no KVM, so this runs under TCG emulation)" + tail -30 "$LOG" + exit 1 +fi +green " login prompt reached" + +# Log in as root (empty password on the live medium) and mark the session so +# the checks can be located unambiguously in the log. +say ""; sleep 2 +say "root"; sleep 8 +say "export PS1= PAGER=cat SYSTEMD_PAGER=cat SYSTEMD_PAGERSECURE=0 SYSTEMD_COLORS=0 TERM=dumb" +sleep 3 +say "stty -echo 2>/dev/null; printf 'SIMOS_SHELL_%s\\n' READY" +if ! wait_for '^SIMOS_SHELL_READY' 240; then + red "serial root login failed"; tail -30 "$LOG"; exit 1 +fi +green " serial root shell obtained" + +# Send a command and wait for its END marker, so slow guests cannot cause +# commands to interleave. Never blocks forever. +# The serial line echoes whatever we type. If the marker literals appeared in +# the command text, every marker would match the ECHO rather than the output: +# wait_for would return instantly and the assertions would match echoed +# command text instead of real results (a silent false pass). +# +# So the markers are ASSEMBLED AT RUNTIME with printf. The typed line contains +# "##BEG%s"/"##EN%s"; only genuine guest output can contain "##BEGIN label" +# and "##END label". +run() { + local label="$1" cmd="$2" limit="${3:-180}" + say "printf '##BEG%s %s\\n' IN $label; { $cmd ; } 2>&1; printf '##EN%s %s\\n' D $label" + if ! wait_for "^##END $label" "$limit"; then + printf ' (timed out collecting %s)\n' "$label" >&2 + fi +} + +info "Waiting for the graphical session to settle (inside the guest)" +run wait-desktop 'for i in $(seq 1 120); do if systemctl is-active --quiet graphical.target && pgrep -f waybar >/dev/null 2>&1 && pgrep -x Hyprland >/dev/null 2>&1; then echo DESKTOP_READY; break; fi; sleep 5; done; systemctl is-active graphical.target' 900 + +info "Collecting live-system state" +run default-target 'systemctl get-default' +run failed-units 'systemctl --failed --no-legend --plain' +run graphical 'systemctl is-active graphical.target' +run displaymanager 'systemctl is-active display-manager.service; systemctl is-active sddm.service' +run sessions 'loginctl list-sessions --no-legend; loginctl list-users --no-legend' +run liveuser 'id liveuser' +run hyprland 'pgrep -a Hyprland || echo NO_HYPRLAND' +run session-procs 'pgrep -a -f "waybar|hyprpaper|mako|hyprpolkitagent|nm-applet" || echo NO_SESSION_PROCS' +run portals 'runuser -u liveuser -- env XDG_RUNTIME_DIR=/run/user/1000 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus busctl --user introspect org.freedesktop.portal.Desktop /org/freedesktop/portal/desktop >/dev/null 2>&1 && echo PORTAL_ACTIVATES || echo PORTAL_NO_ACTIVATE; pgrep -a -f xdg-desktop-portal || true' +run networkmanager 'systemctl is-active NetworkManager; nmcli -t general status; nmcli -t device status' +run dns 'getent hosts archlinux.org || echo DNS_FAIL' +run pipewire 'runuser -u liveuser -- env XDG_RUNTIME_DIR=/run/user/1000 wpctl status 2>&1 | head -20 || echo WPCTL_FAIL' +run calamares-bin 'test -x /usr/bin/calamares && echo CALAMARES_PRESENT || echo CALAMARES_MISSING' +run calamares-cfg 'test -f /usr/share/simulationos/calamares/settings.conf && echo CALAMARES_CFG_PRESENT || echo CALAMARES_CFG_MISSING' +run desktop-entry 'test -f /usr/share/applications/simulationos-install.desktop && echo DESKTOP_PRESENT || echo DESKTOP_MISSING' +run sddm-journal 'journalctl -u sddm --no-pager -n 25 2>&1 | tail -25' +run hypr-journal 'journalctl --no-pager -b -n 200 2>&1 | grep -i -m 20 hyprland || echo NO_HYPRLAND_JOURNAL' + +say "echo SIMOS_CHECKS_DONE" +wait_for 'SIMOS_CHECKS_DONE' 240 || red "checks did not complete cleanly (log may be partial)" + +say "systemctl poweroff"; sleep 10 +kill "$QPID" 2>/dev/null; kill "$CATPID" 2>/dev/null + +# ------------------------------------------------------------------- verdict +printf '\n== live system acceptance\n' +ERRORS=0 +sect() { clean_log | sed -n "/^##BEGIN $1\$/,/^##END $1\$/p" 2>/dev/null; } +assert() { # label, section, pattern + if sect "$2" | grep -aqE "$3"; then green " ok $1"; else red " FAILED $1"; ERRORS=$((ERRORS+1)); fi +} +report() { printf ' ----- %s\n' "$1"; sect "$1" | sed '1d;$d' | sed 's/^/ /' | head -25; } + +assert "desktop reached readiness" wait-desktop 'DESKTOP_READY' +assert "default target is graphical" default-target 'graphical.target' +assert "graphical.target active" graphical '^active$' +assert "display-manager active" displaymanager '^active$' +assert "liveuser exists" liveuser 'uid=1000' +assert "Hyprland running" hyprland 'Hyprland' +assert "session components running" session-procs 'waybar|hyprpaper|mako|hyprpolkitagent' +assert "xdg-desktop-portal present" portals 'PORTAL_ACTIVATES|xdg-desktop-portal' +assert "NetworkManager active" networkmanager '^active$' +assert "DNS resolves" dns 'archlinux\.org' +assert "PipeWire running" pipewire 'PipeWire|Audio' +assert "Calamares installed" calamares-bin 'CALAMARES_PRESENT' +assert "installer config present" calamares-cfg 'CALAMARES_CFG_PRESENT' +assert "installer launcher present" desktop-entry 'DESKTOP_PRESENT' + +printf '\n== diagnostics\n' +for s in failed-units sessions sddm-journal hypr-journal networkmanager pipewire; do report "$s"; done + +printf '\n' +if [ "$ERRORS" -gt 0 ]; then + red "LIVE HEALTH FAILED: $ERRORS check(s) - full log: $LOG"; exit 1 +fi +green "LIVE HEALTH PASSED - full log: $LOG" diff --git a/scripts/make-wallpaper.py b/scripts/make-wallpaper.py new file mode 100755 index 0000000..f73bb51 --- /dev/null +++ b/scripts/make-wallpaper.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 +"""Generate the SimulationOS wallpaper. + +Pure stdlib (zlib + struct) so it runs anywhere without Pillow. Re-run to +regenerate airootfs/usr/share/backgrounds/simulationos/simulationos-alpha.png. +""" +import math +import os +import struct +import sys +import zlib + +W, H = 1920, 1080 +BASE = (0x10, 0x12, 0x16) # near-black +ACCENT = (0x17, 0x93, 0xD1) # SimulationOS blue +GLOW = (0x33, 0xCC, 0xFF) + + +def mix(a, b, t): + t = max(0.0, min(1.0, t)) + return tuple(int(round(a[i] + (b[i] - a[i]) * t)) for i in range(3)) + + +def build_rows(): + cx, cy = W * 0.72, H * 0.28 + maxd = math.hypot(W, H) + rows = [] + for y in range(H): + row = bytearray() + for x in range(W): + # Radial falloff from an off-centre light source. + d = math.hypot(x - cx, y - cy) / maxd + t = max(0.0, 1.0 - d * 1.55) ** 2.2 + r, g, b = mix(BASE, ACCENT, t * 0.85) + + # Diagonal sheen. + sheen = (math.sin((x + y) * math.pi / 900.0) + 1.0) * 0.5 + r, g, b = mix((r, g, b), GLOW, t * sheen * 0.18) + + # Faint 60px "simulation" grid, brighter near the light source. + if x % 60 == 0 or y % 60 == 0: + r, g, b = mix((r, g, b), GLOW, 0.05 + t * 0.10) + + row += bytes((r, g, b)) + rows.append(bytes(row)) + return rows + + +def write_png(path, rows): + raw = b"".join(b"\x00" + r for r in rows) + + def chunk(tag, data): + c = struct.pack(">I", len(data)) + tag + data + return c + struct.pack(">I", zlib.crc32(tag + data) & 0xFFFFFFFF) + + png = b"\x89PNG\r\n\x1a\n" + png += chunk(b"IHDR", struct.pack(">IIBBBBB", W, H, 8, 2, 0, 0, 0)) + png += chunk(b"IDAT", zlib.compress(raw, 9)) + png += chunk(b"IEND", b"") + with open(path, "wb") as fh: + fh.write(png) + + +if __name__ == "__main__": + out = sys.argv[1] if len(sys.argv) > 1 else os.path.join( + os.path.dirname(os.path.dirname(os.path.abspath(__file__))), + "airootfs/usr/share/backgrounds/simulationos/simulationos-alpha.png", + ) + os.makedirs(os.path.dirname(out), exist_ok=True) + write_png(out, build_rows()) + print(f"wrote {out} ({os.path.getsize(out)} bytes, {W}x{H})") diff --git a/scripts/test-iso.sh b/scripts/test-iso.sh new file mode 100755 index 0000000..3692142 --- /dev/null +++ b/scripts/test-iso.sh @@ -0,0 +1,142 @@ +#!/usr/bin/env bash +# +# test-iso.sh - boot a SimulationOS ISO in QEMU. +# +# Defaults to UEFI (OVMF) because that is the primary target; --bios exercises +# the legacy syslinux path. --install attaches a blank disk so a full +# installation can be performed, and --boot-disk then boots ONLY that disk, +# which is the real acceptance test for the installed system. +# +set -euo pipefail + +REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +OUT="${SIMOS_OUT_DIR:-$REPO/out}" + +FIRMWARE="uefi" +ISO="" +DISK="$OUT/simulationos-test.qcow2" +DISK_SIZE="${SIMOS_TEST_DISK_SIZE:-30G}" +ATTACH_DISK=0 +BOOT_DISK_ONLY=0 +RAM="${SIMOS_TEST_RAM:-4096}" +CPUS="${SIMOS_TEST_CPUS:-2}" + +usage() { + cat <<'EOF' +usage: test-iso.sh [options] [path/to.iso] + + --uefi boot via OVMF (default) + --bios boot via legacy BIOS / syslinux + --install attach a blank virtual disk for an installation run + --boot-disk boot ONLY the virtual disk (no ISO attached) - verifies + the installed system boots independently of the medium + --ram MB guest memory (default 4096) + +Environment: + SIMOS_QEMU_AUDIODEV QEMU audio backend (default "none" = silent but always + works). Set to pa, alsa or coreaudio for real sound. + --cpus N guest vCPUs (default 2) + +If no ISO path is given, the newest out/simulationos-*.iso is used. + +Typical acceptance run: + ./scripts/test-iso.sh --install # boot ISO, install to the blank disk + ./scripts/test-iso.sh --boot-disk # reboot from the disk alone +EOF +} + +while [ $# -gt 0 ]; do + case "$1" in + --uefi) FIRMWARE="uefi" ;; + --bios) FIRMWARE="bios" ;; + --install) ATTACH_DISK=1 ;; + --boot-disk) BOOT_DISK_ONLY=1; ATTACH_DISK=1 ;; + --ram) RAM="$2"; shift ;; + --cpus) CPUS="$2"; shift ;; + -h|--help) usage; exit 0 ;; + *) ISO="$1" ;; + esac + shift +done + +die() { printf 'ERROR: %s\n' "$*" >&2; exit 1; } + +command -v qemu-system-x86_64 >/dev/null \ + || die "qemu-system-x86_64 not found. Install qemu-full (Arch) or qemu-system-x86 (Debian/Fedora)." + +if [ "$BOOT_DISK_ONLY" -eq 0 ]; then + [ -n "$ISO" ] || ISO="$(ls -1t "$OUT"/simulationos-*.iso 2>/dev/null | head -1 || true)" + [ -n "$ISO" ] || die "No ISO given and none found in $OUT. Run scripts/build-iso.sh first." + [ -f "$ISO" ] || die "ISO not found: $ISO" +fi + +# virtio-vga-gl + gl=on gives Hyprland a GPU to render on. Without it the +# session falls back to llvmpipe, which works but is slow. +# shellcheck disable=SC2054 # commas are part of QEMU option values, not separators +QEMU=(qemu-system-x86_64 + -machine q35,accel=kvm:tcg + -cpu max + -smp "$CPUS" + -m "$RAM" + -device virtio-vga-gl + -display gtk,gl=on + -audiodev "${SIMOS_QEMU_AUDIODEV:-none},id=snd0" + -device intel-hda -device hda-duplex,audiodev=snd0 + -device virtio-net-pci,netdev=n0 -netdev user,id=n0 + -device qemu-xhci -device usb-tablet) + +if [ "$FIRMWARE" = "uefi" ]; then + OVMF_CODE="" + for c in /opt/homebrew/share/qemu/edk2-x86_64-code.fd \ + /usr/local/share/qemu/edk2-x86_64-code.fd \ + /usr/share/edk2/x64/OVMF_CODE.4m.fd \ + /usr/share/edk2/x64/OVMF_CODE.fd \ + /usr/share/edk2-ovmf/x64/OVMF_CODE.fd \ + /usr/share/OVMF/OVMF_CODE_4M.fd \ + /usr/share/OVMF/OVMF_CODE.fd; do + [ -f "$c" ] && { OVMF_CODE="$c"; break; } + done + [ -n "$OVMF_CODE" ] \ + || die "OVMF firmware not found. Install 'edk2-ovmf' (Arch) or 'ovmf' (Debian/Fedora), or use --bios." + + OVMF_VARS_SRC="" + for v in /opt/homebrew/share/qemu/edk2-i386-vars.fd \ + /usr/local/share/qemu/edk2-i386-vars.fd \ + /usr/share/edk2/x64/OVMF_VARS.4m.fd \ + /usr/share/edk2/x64/OVMF_VARS.fd \ + /usr/share/edk2-ovmf/x64/OVMF_VARS.fd \ + /usr/share/OVMF/OVMF_VARS_4M.fd \ + /usr/share/OVMF/OVMF_VARS.fd; do + [ -f "$v" ] && { OVMF_VARS_SRC="$v"; break; } + done + [ -n "$OVMF_VARS_SRC" ] || die "OVMF variable template not found alongside $OVMF_CODE." + + mkdir -p "$OUT" + OVMF_VARS="$OUT/OVMF_VARS.simulationos.fd" + # A per-test writable copy, so UEFI boot entries written by the installer + # persist across runs (needed for the --boot-disk acceptance test). + [ -f "$OVMF_VARS" ] || cp "$OVMF_VARS_SRC" "$OVMF_VARS" + + QEMU+=(-drive "if=pflash,format=raw,unit=0,readonly=on,file=$OVMF_CODE" + -drive "if=pflash,format=raw,unit=1,file=$OVMF_VARS") +fi + +if [ "$ATTACH_DISK" -eq 1 ]; then + if [ ! -f "$DISK" ]; then + printf '==> Creating blank test disk %s (%s)\n' "$DISK" "$DISK_SIZE" + mkdir -p "$OUT" + qemu-img create -f qcow2 "$DISK" "$DISK_SIZE" >/dev/null + fi + QEMU+=(-drive "file=$DISK,if=virtio,format=qcow2") +fi + +if [ "$BOOT_DISK_ONLY" -eq 1 ]; then + printf '==> Booting ONLY the installed disk, no ISO attached\n' + QEMU+=(-boot order=c) +else + QEMU+=(-drive "file=$ISO,media=cdrom,readonly=on" -boot order=d) + printf '==> Booting %s (%s)\n' "$(basename "$ISO")" "$FIRMWARE" +fi + +printf '==> %s\n' "${QEMU[*]}" +exec "${QEMU[@]}" diff --git a/scripts/validate-profile.sh b/scripts/validate-profile.sh new file mode 100755 index 0000000..7984118 --- /dev/null +++ b/scripts/validate-profile.sh @@ -0,0 +1,529 @@ +#!/usr/bin/env bash +# +# validate-profile.sh - static consistency checks for the SimulationOS profile. +# +# Catches the class of breakage that only shows up hours into a build or, worse, +# at boot: boot entries pointing at a kernel that is not installed, desktop +# configs launching binaries nobody ships, personal paths, dangling symlinks, +# Calamares referring to modules or scripts that do not exist. +# +# Runs anywhere with bash 3.2+ (macOS included) - it never needs pacman. +# Exit status: 0 = clean, 1 = errors found. +# +set -u + +REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$REPO" || exit 1 + +ERRORS=0 +WARNINGS=0 +CHECKS=0 + +red() { printf '\033[31m%s\033[0m\n' "$*"; } +yellow(){ printf '\033[33m%s\033[0m\n' "$*"; } +green() { printf '\033[32m%s\033[0m\n' "$*"; } + +err() { ERRORS=$((ERRORS+1)); red " ERROR $*"; } +warn() { WARNINGS=$((WARNINGS+1)); yellow " WARN $*"; } +ok() { CHECKS=$((CHECKS+1)); } +section() { printf '\n== %s\n' "$*"; } + +# Packages the profile installs (comments and blanks stripped). +PKGLIST="$(grep -vE '^[[:space:]]*(#|$)' packages.x86_64 2>/dev/null)" +has_pkg() { printf '%s\n' "$PKGLIST" | grep -qx -- "$1"; } + +# --------------------------------------------------------------------------- +section "profiledef.sh" +# --------------------------------------------------------------------------- +if [ ! -f profiledef.sh ]; then + err "profiledef.sh is missing" +else + bash -n profiledef.sh 2>/dev/null || err "profiledef.sh has a syntax error" + ok + + # Evaluate declarations only - comments legitimately mention bootmode names. + PROFILE_CODE="$(sed 's/[[:space:]]*#.*$//' profiledef.sh)" + + # Deprecated / removed archiso boot mode names. + for bad in bios.syslinux.mbr bios.syslinux.eltorito \ + uefi-x64.systemd-boot.esp uefi-x64.systemd-boot.eltorito \ + uefi-ia32.systemd-boot.esp uefi-ia32.systemd-boot.eltorito \ + uefi-x64.grub.esp uefi-x64.grub.eltorito \ + uefi-ia32.grub.esp uefi-ia32.grub.eltorito; do + if printf '%s\n' "$PROFILE_CODE" | grep -q "'$bad'"; then + err "profiledef.sh uses deprecated bootmode '$bad'" + fi + done + ok + + # mkarchiso rejects these two together. + if printf '%s\n' "$PROFILE_CODE" | grep -q "'uefi.systemd-boot'" \ + && printf '%s\n' "$PROFILE_CODE" | grep -q "'uefi.grub'"; then + err "bootmodes uefi.systemd-boot and uefi.grub cannot be combined" + fi + ok + + # Variables mkarchiso does not consume. + for fake in iso_icon profiles_description install_dir_disktop kernel_parameters; do + printf '%s\n' "$PROFILE_CODE" | grep -qE "^[[:space:]]*${fake}=" \ + && err "profiledef.sh sets '$fake', which mkarchiso does not read" + done + ok + + # grub/grub.cfg is only consumed by the uefi.grub bootmode. + if [ -f grub/grub.cfg ] && ! printf '%s\n' "$PROFILE_CODE" | grep -q "'uefi.grub'"; then + err "grub/grub.cfg exists but 'uefi.grub' is not a bootmode (dead file)" + fi + ok + + # file_permissions entries must point at files that exist. + sed -n 's/^[[:space:]]*\["\([^"]*\)"\].*/\1/p' profiledef.sh | while read -r fp; do + [ -z "$fp" ] && continue + if [ ! -e "airootfs${fp}" ] && [ ! -L "airootfs${fp}" ]; then + red " ERROR file_permissions references missing path: airootfs${fp}" + echo x >>"$REPO/.validate_fperm_fail" + fi + done + if [ -f .validate_fperm_fail ]; then + ERRORS=$((ERRORS + $(wc -l < .validate_fperm_fail))) + rm -f .validate_fperm_fail + fi + ok +fi + +# --------------------------------------------------------------------------- +section "kernel / boot consistency" +# --------------------------------------------------------------------------- +# Derive the kernel pkgbase from the package list, then require that every +# boot entry references exactly that kernel's files. +KPKG="" +for cand in $(printf '%s\n' "$PKGLIST" \ + | grep -E '^linux(-[a-z0-9]+)*$' \ + | grep -vE '^linux-(firmware|api-headers|atm)' \ + | grep -vE -- '-headers$'); do + KPKG="$cand" +done +if [ -z "$KPKG" ]; then + err "no kernel package (linux*) found in packages.x86_64" +else + green " kernel package: $KPKG" + VMLINUZ="vmlinuz-${KPKG}" + INITRAMFS="initramfs-${KPKG}.img" + + BOOTFILES="efiboot/loader/entries/*.conf syslinux/archiso_sys-linux.cfg syslinux/archiso_pxe-linux.cfg grub/loopback.cfg" + for f in $BOOTFILES; do + [ -f "$f" ] || continue + # Any vmlinuz-* reference that is not our kernel is a mismatch. + bad="$(grep -oE 'vmlinuz-[A-Za-z0-9._-]+' "$f" | grep -v "^${VMLINUZ}$" | sort -u)" + if [ -n "$bad" ]; then + err "$f references kernel image(s) [$(echo "$bad" | tr '\n' ' ')] but the profile installs $VMLINUZ" + fi + bad="$(grep -oE 'initramfs-[A-Za-z0-9._-]+\.img' "$f" | grep -vE "^initramfs-${KPKG}(-fallback)?\.img$" | sort -u)" + if [ -n "$bad" ]; then + err "$f references initramfs [$(echo "$bad" | tr '\n' ' ')] but the profile installs $INITRAMFS" + fi + done + ok + + # Custom mkinitcpio presets are a classic source of kernel-name drift. + if [ -d airootfs/etc/mkinitcpio.d ]; then + err "airootfs/etc/mkinitcpio.d exists; upstream archiso removed custom presets (the auto-generated ${KPKG}.preset is correct)" + fi + ok + + # systemd-boot default entry must exist. + if [ -f efiboot/loader/loader.conf ]; then + DEF="$(sed -n 's/^default[[:space:]]\+//p' efiboot/loader/loader.conf | head -1)" + if [ -n "$DEF" ] && [ ! -f "efiboot/loader/entries/$DEF" ]; then + err "loader.conf default entry '$DEF' does not exist in efiboot/loader/entries/" + fi + fi + ok + + # archiso hard requirements. + has_pkg mkinitcpio || err "packages.x86_64 is missing mandatory package 'mkinitcpio'" + has_pkg mkinitcpio-archiso || err "packages.x86_64 is missing mandatory package 'mkinitcpio-archiso'" + ok + + # Every mkinitcpio hook must have its support package, or mkinitcpio fails + # late in the build with "file not found: /usr/lib/initcpio/...". + MKCONF=airootfs/etc/mkinitcpio.conf.d/archiso.conf + if [ -f "$MKCONF" ]; then + HOOKS_LINE="$(sed -n 's/^HOOKS=(\(.*\))/\1/p' "$MKCONF")" + for h in $HOOKS_LINE; do + case "$h" in + archiso_pxe_common|archiso_pxe_nfs) + has_pkg mkinitcpio-nfs-utils \ + || err "mkinitcpio hook '$h' needs 'mkinitcpio-nfs-utils' in packages.x86_64" ;; + archiso_pxe_nbd) + has_pkg nbd \ + || err "mkinitcpio hook '$h' needs 'nbd' in packages.x86_64" ;; + archiso|archiso_loop_mnt|memdisk) + has_pkg mkinitcpio-archiso \ + || err "mkinitcpio hook '$h' needs 'mkinitcpio-archiso'" ;; + esac + done + # A syslinux PXE config with no PXE hooks is dead configuration. + if [ -f syslinux/archiso_pxe.cfg ] && ! printf '%s' "$HOOKS_LINE" | grep -q archiso_pxe; then + err "syslinux/archiso_pxe.cfg exists but no archiso_pxe* mkinitcpio hook is enabled (dead PXE config)" + fi + fi + ok +fi + +# --------------------------------------------------------------------------- +section "packages.x86_64" +# --------------------------------------------------------------------------- +DUPES="$(printf '%s\n' "$PKGLIST" | sort | uniq -d)" +[ -n "$DUPES" ] && err "duplicate package entries: $(echo "$DUPES" | tr '\n' ' ')" +ok + +# Security posture of the shipped pacman configuration. +for pc in pacman.conf airootfs/etc/pacman.conf; do + [ -f "$pc" ] || continue + grep -qE '^[[:space:]]*DisableSandbox' "$pc" \ + && err "$pc sets DisableSandbox; the pacman sandbox must stay on in the committed profile (the emulated builder patches a throwaway copy instead)" + grep -qE '^[[:space:]]*SigLevel[[:space:]]*=.*Never' "$pc" \ + && err "$pc disables signature verification (SigLevel ... Never)" + grep -qE '^[[:space:]]*SigLevel[[:space:]]*=[[:space:]]*Required' "$pc" \ + || err "$pc does not set 'SigLevel = Required ...'" +done +ok + +# Packages known to have been dropped from the Arch repositories. +for gone in broadcom-wl rofi-wayland libva-mesa-driver ckbcomp-nonfree; do + has_pkg "$gone" && err "packages.x86_64 lists '$gone', which no longer exists in the Arch repositories" +done +ok + +# A graphical profile needs these to reach a desktop at all. +for need in hyprland sddm networkmanager pipewire wireplumber xdg-desktop-portal-hyprland polkit; do + has_pkg "$need" || err "packages.x86_64 is missing '$need', required for the graphical live session" +done +ok + +# --------------------------------------------------------------------------- +section "developer-specific and stale paths" +# --------------------------------------------------------------------------- +SCAN="$(find airootfs syslinux efiboot grub -type f 2>/dev/null)" +for pat in '/mnt/m\.2' '/mnt/[a-z0-9_]*ssd' '/Users/' '/home/[a-z]*/\.config' 'ml4w' 'grimblast' 'auto-cpufreq' 'trash-put'; do + for f in $SCAN; do + # Strip comments first: naming a tool in prose is not a dependency. + if sed -e 's/[[:space:]]*#.*$//' -e 's|[[:space:]]*//.*$||' "$f" 2>/dev/null \ + | grep -qE "$pat"; then + err "developer-specific reference '$pat' in: $f" + fi + done +done +ok + +# Stale upstream branding in user-visible boot menus. +HITS="$(grep -rl 'Arch Linux install medium' efiboot syslinux grub 2>/dev/null)" +[ -n "$HITS" ] && err "stale Arch branding in boot menu: $(echo "$HITS" | tr '\n' ' ')" +HITS="$(grep -rl 'CachyOS' airootfs/etc/os-release airootfs/etc/issue airootfs/etc/motd \ + airootfs/etc/simulationos-release efiboot syslinux grub 2>/dev/null)" +[ -n "$HITS" ] && err "CachyOS branding on a SimulationOS identity surface: $(echo "$HITS" | tr '\n' ' ')" +ok + +# A black screen on first boot is indistinguishable from a broken session. +if grep -rq 'brightnessctl set 0%' airootfs 2>/dev/null; then + err "'brightnessctl set 0%' would blank the display on first login" +fi +ok + +# --------------------------------------------------------------------------- +section "Hyprland session" +# --------------------------------------------------------------------------- +HYPR=airootfs/etc/skel/.config/hypr/hyprland.conf +if [ ! -f "$HYPR" ]; then + err "$HYPR is missing" +else + # Every sourced file must exist. + grep -E '^[[:space:]]*source[[:space:]]*=' "$HYPR" | sed 's/.*=[[:space:]]*//' | while read -r src; do + rel="$(printf '%s' "$src" | sed 's|^~/.config/|airootfs/etc/skel/.config/|')" + if [ ! -f "$rel" ]; then + red " ERROR hyprland.conf sources missing file: $src" + echo x >>"$REPO/.validate_src_fail" + fi + done + if [ -f .validate_src_fail ]; then + ERRORS=$((ERRORS + $(wc -l < .validate_src_fail))); rm -f .validate_src_fail + fi + ok + + # Every exec-once / exec target must be a shipped package binary or a + # script we ship in airootfs/usr/local/bin. + CMDS="$(grep -E '^[[:space:]]*(exec-once|exec)[[:space:]]*=' "$HYPR" \ + | sed 's/.*=[[:space:]]*//' | awk '{print $1}' | sort -u)" + # Map binary -> providing package for the ones that differ in name. + for cmd in $CMDS; do + case "$cmd" in + dbus-update-activation-environment|systemctl) continue ;; # from dbus/systemd in base + esac + if [ -f "airootfs/usr/local/bin/$cmd" ]; then continue; fi + prov="$cmd" + case "$cmd" in + nm-applet) prov=network-manager-applet ;; + blueman-applet) prov=blueman ;; + wl-paste) prov=wl-clipboard ;; + wpctl) prov=wireplumber ;; + esac + has_pkg "$prov" || err "hyprland.conf runs '$cmd' but package '$prov' is not in packages.x86_64" + done + ok + + # Keybind targets that are our own scripts must exist. + for s in simos-screenshot simos-powermenu simos-clipboard; do + if grep -q "$s" "$HYPR"; then + [ -x "airootfs/usr/local/bin/$s" ] \ + || err "hyprland.conf binds '$s' but airootfs/usr/local/bin/$s is missing or not executable" + fi + done + ok +fi + +# Wallpaper referenced by hyprpaper must exist. +HP=airootfs/etc/skel/.config/hypr/hyprpaper.conf +if [ -f "$HP" ]; then + grep -E '^[[:space:]]*(preload|wallpaper)[[:space:]]*=' "$HP" \ + | sed 's/.*[=,][[:space:]]*//' | grep '^/' | sort -u | while read -r img; do + if [ ! -f "airootfs${img}" ]; then + red " ERROR hyprpaper references missing image: $img" + echo x >>"$REPO/.validate_wp_fail" + fi + done + if [ -f .validate_wp_fail ]; then + ERRORS=$((ERRORS + $(wc -l < .validate_wp_fail))); rm -f .validate_wp_fail + fi +fi +ok + +# Exactly one wallpaper daemon. +WPD=0 +for d in hyprpaper swww swaybg wpaperd; do + grep -rqE "exec-once[[:space:]]*=[[:space:]]*$d" airootfs/etc/skel/.config/hypr 2>/dev/null && WPD=$((WPD+1)) +done +[ "$WPD" -gt 1 ] && err "more than one wallpaper daemon is started from the Hyprland config" +ok + +# --------------------------------------------------------------------------- +section "display manager / session" +# --------------------------------------------------------------------------- +DM=airootfs/etc/systemd/system/display-manager.service +if [ -L "$DM" ]; then + TGT="$(readlink "$DM")" + case "$TGT" in + */sddm.service) has_pkg sddm || err "display-manager.service points at sddm but sddm is not installed" ;; + */gdm.service) has_pkg gdm || err "display-manager.service points at gdm but gdm is not installed" ;; + *) warn "display-manager.service points at an unrecognised unit: $TGT" ;; + esac +else + err "airootfs/etc/systemd/system/display-manager.service is missing (no display manager will start)" +fi +ok + +if [ -L airootfs/etc/systemd/system/default.target ]; then + case "$(readlink airootfs/etc/systemd/system/default.target)" in + */graphical.target) ;; + *) err "default.target does not point at graphical.target" ;; + esac +else + err "airootfs/etc/systemd/system/default.target is missing" +fi +ok + +# Dangling systemd .wants symlinks inside airootfs must at least name a unit +# path that a shipped package could provide. +find airootfs/etc/systemd -type l 2>/dev/null | while read -r link; do + tgt="$(readlink "$link")" + case "$tgt" in + /usr/lib/systemd/*|/dev/null) + ;; + /etc/systemd/system/*) + # absolute link into our own overlay - the unit must be shipped + [ -f "airootfs${tgt}" ] || { red " ERROR $link -> $tgt (unit not shipped)"; echo x >>"$REPO/.validate_sl_fail"; } + ;; + /*) + red " ERROR systemd symlink escapes to an unexpected path: $link -> $tgt" + echo x >>"$REPO/.validate_sl_fail" + ;; + *) + # relative link - must resolve inside airootfs + [ -e "$(dirname "$link")/$tgt" ] || { red " ERROR dangling systemd symlink $link -> $tgt"; echo x >>"$REPO/.validate_sl_fail"; } + ;; + esac +done +if [ -f .validate_sl_fail ]; then + ERRORS=$((ERRORS + $(wc -l < .validate_sl_fail))); rm -f .validate_sl_fail +fi +ok + +# Only one network stack may be enabled. +NMW=airootfs/etc/systemd/system/multi-user.target.wants/NetworkManager.service +NDW=airootfs/etc/systemd/system/multi-user.target.wants/systemd-networkd.service +if { [ -e "$NDW" ] || [ -L "$NDW" ]; } && { [ -e "$NMW" ] || [ -L "$NMW" ]; }; then + err "both systemd-networkd and NetworkManager are enabled" +fi +{ [ -e "$NMW" ] || [ -L "$NMW" ]; } \ + || err "NetworkManager.service is not enabled in the live environment" +ok + +# --------------------------------------------------------------------------- +section "Calamares installer" +# --------------------------------------------------------------------------- +CALDIR=airootfs/usr/share/simulationos/calamares +if [ ! -f "$CALDIR/settings.conf" ]; then + err "$CALDIR/settings.conf is missing" +else + # Modules that legitimately need no .conf. + CONFIGLESS="umount" + MODS="$(sed -n '/^sequence:/,/^branding:/p' "$CALDIR/settings.conf" \ + | grep -E '^[[:space:]]*-[[:space:]]*[a-z]' \ + | sed -e 's/^[[:space:]]*-[[:space:]]*//' -e 's/:[[:space:]]*$//' \ + | grep -vE '^(show|exec)$' | sort -u)" + for m in $MODS; do + base="${m%%@*}" + inst="${m##*@}" + if [ "$base" != "$m" ]; then + # instance form module@id -> settings.conf must declare it + grep -q "id:[[:space:]]*$inst" "$CALDIR/settings.conf" \ + || err "settings.conf uses '$m' but declares no instance with id '$inst'" + cfg="$(grep -A2 "id:[[:space:]]*$inst" "$CALDIR/settings.conf" | sed -n 's/.*config:[[:space:]]*//p' | head -1)" + [ -n "$cfg" ] && [ ! -f "$CALDIR/modules/$cfg" ] \ + && err "instance '$inst' references missing config $CALDIR/modules/$cfg" + else + if ! printf '%s\n' "$CONFIGLESS" | grep -qx "$base"; then + [ -f "$CALDIR/modules/$base.conf" ] \ + || err "Calamares module '$base' has no config at $CALDIR/modules/$base.conf" + fi + fi + done + ok + + # Branding must resolve. + BR="$(sed -n 's/^branding:[[:space:]]*//p' "$CALDIR/settings.conf" | head -1)" + if [ -n "$BR" ]; then + [ -f "$CALDIR/branding/$BR/branding.desc" ] \ + || err "branding '$BR' has no branding.desc at $CALDIR/branding/$BR/" + if [ -f "$CALDIR/branding/$BR/branding.desc" ]; then + sed -n 's/^[[:space:]]*\(productLogo\|productIcon\|productWelcome\|slideshow\):[[:space:]]*"\{0,1\}\([^"]*\)"\{0,1\}[[:space:]]*$/\2/p' \ + "$CALDIR/branding/$BR/branding.desc" | while read -r img; do + [ -z "$img" ] && continue + [ -f "$CALDIR/branding/$BR/$img" ] || { red " ERROR branding asset missing: $img"; echo x >>"$REPO/.validate_br_fail"; } + done + if [ -f .validate_br_fail ]; then + ERRORS=$((ERRORS + $(wc -l < .validate_br_fail))); rm -f .validate_br_fail + fi + fi + fi + ok + + # Scripts referenced by shellprocess configs must exist and be executable. + for sp in "$CALDIR"/modules/shellprocess*.conf; do + [ -f "$sp" ] || continue + grep -oE '"/usr/share/simulationos[^"]*"' "$sp" | tr -d '"' | while read -r s; do + [ -x "airootfs$s" ] || { red " ERROR $sp references missing/non-executable $s"; echo x >>"$REPO/.validate_sp_fail"; } + done + done + if [ -f .validate_sp_fail ]; then + ERRORS=$((ERRORS + $(wc -l < .validate_sp_fail))); rm -f .validate_sp_fail + fi + ok + + # The unpackfs source path must match install_dir/arch from profiledef.sh. + IDIR="$(sed -n 's/^install_dir="\(.*\)"/\1/p' profiledef.sh | head -1)" + IARCH="$(sed -n 's/^arch="\(.*\)"/\1/p' profiledef.sh | head -1)" + if [ -f "$CALDIR/modules/unpackfs.conf" ] && [ -n "$IDIR" ] && [ -n "$IARCH" ]; then + EXPECT="/run/archiso/bootmnt/${IDIR}/${IARCH}/airootfs.sfs" + grep -q "$EXPECT" "$CALDIR/modules/unpackfs.conf" \ + || err "unpackfs.conf source does not match profiledef (expected $EXPECT)" + fi + ok + + # The installer must actually be installable and launchable. + has_pkg cachyos-calamares || has_pkg calamares \ + || err "no Calamares package in packages.x86_64, but an installer config exists" + [ -x airootfs/usr/local/bin/simulationos-install ] \ + || err "airootfs/usr/local/bin/simulationos-install is missing or not executable" + [ -f airootfs/usr/share/applications/simulationos-install.desktop ] \ + || err "installer .desktop launcher is missing" + if [ -f airootfs/usr/share/applications/simulationos-install.desktop ]; then + EXEC="$(sed -n 's/^Exec=//p' airootfs/usr/share/applications/simulationos-install.desktop | awk '{print $1}')" + [ -x "airootfs$EXEC" ] || err ".desktop Exec points at missing $EXEC" + ICON="$(sed -n 's/^Icon=//p' airootfs/usr/share/applications/simulationos-install.desktop)" + if [ -n "$ICON" ] && [ "${ICON#/}" = "$ICON" ]; then + ls airootfs/usr/share/pixmaps/"$ICON".* >/dev/null 2>&1 \ + || warn ".desktop Icon='$ICON' not found in airootfs/usr/share/pixmaps/" + fi + fi + ok + + # The live medium must not leak into the installed system. + DELOOP="$CALDIR/scripts/simulationos-deloop" + if [ -f "$DELOOP" ]; then + for must in 'mkinitcpio.conf.d/archiso.conf' 'live-autologin' '10-simulationos-live' 'passwd --lock root' '/home/liveuser'; do + grep -q -- "$must" "$DELOOP" \ + || err "simulationos-deloop does not handle '$must'" + done + fi + grep -q 'username:[[:space:]]*liveuser' "$CALDIR/modules/removeuser.conf" 2>/dev/null \ + || err "removeuser.conf does not remove 'liveuser'" + grep -qE '^[[:space:]]*doAutologin:[[:space:]]*false' "$CALDIR/modules/users.conf" 2>/dev/null \ + || err "users.conf does not set doAutologin: false (live autologin would be inherited)" + ok +fi + +# --------------------------------------------------------------------------- +section "shell scripts" +# --------------------------------------------------------------------------- +SCRIPTS="$(find airootfs/usr/local/bin airootfs/usr/share/simulationos -type f 2>/dev/null; ls scripts/*.sh 2>/dev/null)" +for s in $SCRIPTS; do + head -1 "$s" | grep -q '^#!' || continue + if ! bash -n "$s" 2>/dev/null; then + err "shell syntax error in $s" + fi + [ -x "$s" ] || err "$s has a shebang but is not executable" +done +ok + +if command -v shellcheck >/dev/null 2>&1; then + for s in $SCRIPTS; do + head -1 "$s" | grep -qE '^#!.*(bash|sh)' || continue + out="$(shellcheck -S error -f gcc "$s" 2>/dev/null)" + [ -n "$out" ] && err "shellcheck errors in $s:"$'\n'"$out" + done + ok +else + warn "shellcheck not installed; skipping lint" +fi + +# --------------------------------------------------------------------------- +section "broken symlinks inside airootfs" +# --------------------------------------------------------------------------- +# Only symlinks that point *within* airootfs can be checked offline; absolute +# links into /usr are resolved on the target at build time. +find airootfs -type l 2>/dev/null | while read -r l; do + t="$(readlink "$l")" + case "$t" in + /*) continue ;; + esac + d="$(dirname "$l")" + [ -e "$d/$t" ] || { red " ERROR broken relative symlink: $l -> $t"; echo x >>"$REPO/.validate_bs_fail"; } +done +if [ -f .validate_bs_fail ]; then + ERRORS=$((ERRORS + $(wc -l < .validate_bs_fail))); rm -f .validate_bs_fail +fi +ok + +# --------------------------------------------------------------------------- +printf '\n' +if [ "$ERRORS" -gt 0 ]; then + red "FAILED: $ERRORS error(s), $WARNINGS warning(s)" + exit 1 +fi +if [ "$WARNINGS" -gt 0 ]; then + yellow "PASSED with $WARNINGS warning(s)" + exit 0 +fi +green "PASSED: profile is internally consistent" +exit 0 diff --git a/syslinux/archiso_head.cfg b/syslinux/archiso_head.cfg index 671ab4e..b8d6810 100644 --- a/syslinux/archiso_head.cfg +++ b/syslinux/archiso_head.cfg @@ -1,6 +1,6 @@ SERIAL 0 115200 UI vesamenu.c32 -MENU TITLE Arch Linux +MENU TITLE SimulationOS MENU BACKGROUND splash.png MENU WIDTH 78 diff --git a/syslinux/archiso_pxe-linux.cfg b/syslinux/archiso_pxe-linux.cfg deleted file mode 100644 index 5d0f741..0000000 --- a/syslinux/archiso_pxe-linux.cfg +++ /dev/null @@ -1,32 +0,0 @@ -LABEL arch64_nbd -TEXT HELP -Boot the Arch Linux install medium using NBD. -It allows you to install Arch Linux or perform system maintenance. -ENDTEXT -MENU LABEL Arch Linux install medium (x86_64, NBD) -LINUX ::/%INSTALL_DIR%/boot/x86_64/vmlinuz-linux -INITRD ::/%INSTALL_DIR%/boot/x86_64/initramfs-linux.img -APPEND archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID% archiso_nbd_srv=${pxeserver} cms_verify=y -SYSAPPEND 3 - -LABEL arch64_nfs -TEXT HELP -Boot the Arch Linux live medium using NFS. -It allows you to install Arch Linux or perform system maintenance. -ENDTEXT -MENU LABEL Arch Linux install medium (x86_64, NFS) -LINUX ::/%INSTALL_DIR%/boot/x86_64/vmlinuz-linux -INITRD ::/%INSTALL_DIR%/boot/x86_64/initramfs-linux.img -APPEND archisobasedir=%INSTALL_DIR% archiso_nfs_srv=${pxeserver}:/run/archiso/bootmnt cms_verify=y -SYSAPPEND 3 - -LABEL arch64_http -TEXT HELP -Boot the Arch Linux live medium using HTTP. -It allows you to install Arch Linux or perform system maintenance. -ENDTEXT -MENU LABEL Arch Linux install medium (x86_64, HTTP) -LINUX ::/%INSTALL_DIR%/boot/x86_64/vmlinuz-linux -INITRD ::/%INSTALL_DIR%/boot/x86_64/initramfs-linux.img -APPEND archisobasedir=%INSTALL_DIR% archiso_http_srv=http://${pxeserver}/ cms_verify=y -SYSAPPEND 3 diff --git a/syslinux/archiso_pxe.cfg b/syslinux/archiso_pxe.cfg deleted file mode 100644 index b4c9a80..0000000 --- a/syslinux/archiso_pxe.cfg +++ /dev/null @@ -1,5 +0,0 @@ -INCLUDE archiso_head.cfg - -INCLUDE archiso_pxe-linux.cfg - -INCLUDE archiso_tail.cfg diff --git a/syslinux/archiso_sys-linux.cfg b/syslinux/archiso_sys-linux.cfg index 919e158..3140aa5 100644 --- a/syslinux/archiso_sys-linux.cfg +++ b/syslinux/archiso_sys-linux.cfg @@ -1,20 +1,19 @@ -LABEL arch64 +LABEL simulationos TEXT HELP -Boot the Arch Linux install medium on BIOS. -It allows you to install Arch Linux or perform system maintenance. +Boot SimulationOS on BIOS. +Starts the live Hyprland desktop, from which SimulationOS can be installed. ENDTEXT -MENU LABEL Arch Linux install medium (x86_64, BIOS) -LINUX /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux -INITRD /%INSTALL_DIR%/boot/x86_64/initramfs-linux.img -APPEND archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID% +MENU LABEL SimulationOS (%ARCH%, BIOS) +LINUX /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux-cachyos +INITRD /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux-cachyos.img +APPEND archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID% console=ttyS0,115200 console=tty0 %KERNEL_PARAMS% # Accessibility boot option -LABEL arch64speech +LABEL simulationosspeech TEXT HELP -Boot the Arch Linux install medium on BIOS with speakup screen reader. -It allows you to install Arch Linux or perform system maintenance with speech feedback. +Boot SimulationOS on BIOS with the speakup screen reader. ENDTEXT -MENU LABEL Arch Linux install medium (x86_64, BIOS) with ^speech -LINUX /%INSTALL_DIR%/boot/x86_64/vmlinuz-linux -INITRD /%INSTALL_DIR%/boot/x86_64/initramfs-linux.img -APPEND archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID% accessibility=on +MENU LABEL SimulationOS (%ARCH%, BIOS) with ^speech +LINUX /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux-cachyos +INITRD /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux-cachyos.img +APPEND archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID% accessibility=on console=ttyS0,115200 console=tty0 %KERNEL_PARAMS% diff --git a/syslinux/archiso_sys.cfg b/syslinux/archiso_sys.cfg index d93bcfe..1b8b1b9 100644 --- a/syslinux/archiso_sys.cfg +++ b/syslinux/archiso_sys.cfg @@ -1,6 +1,6 @@ INCLUDE archiso_head.cfg -DEFAULT arch64 +DEFAULT simulationos TIMEOUT 150 INCLUDE archiso_sys-linux.cfg diff --git a/syslinux/syslinux.cfg b/syslinux/syslinux.cfg index cbda72f..672fae0 100644 --- a/syslinux/syslinux.cfg +++ b/syslinux/syslinux.cfg @@ -1,11 +1,4 @@ -DEFAULT select - -LABEL select -COM32 whichsys.c32 -APPEND -pxe- pxe -sys- sys -iso- sys - -LABEL pxe -CONFIG archiso_pxe.cfg - +# SimulationOS does not support PXE netboot, so there is no pxe branch here. +DEFAULT sys LABEL sys CONFIG archiso_sys.cfg