commit 6dcb1bb76873ac8f62376401c4124d0c56ace04e from: Alejandro Bernal Estrada date: Fri May 22 00:40:27 2026 UTC add: CI audit workflow, script 58 checks, README completo; fix:kernel-loadable-modules nvidia-module commit - 4c05a15cfa439f1fcc11e58ce8844d9fcf35c0c9 commit + 6dcb1bb76873ac8f62376401c4124d0c56ace04e blob - /dev/null blob + 58eb2e043e09c04d1151664c005a9d48d1570337 (mode 644) --- /dev/null +++ .forgejo/workflows/audit.yml @@ -0,0 +1,30 @@ +# .forgejo/workflows/audit.yml +# +# Forgejo Actions — Verificación estática del canal Guix. +# Corre en cada push y pull request a main. +# El badge del resultado aparece en el README. + +name: Audit + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + audit: + name: Static Audit + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Run audit + run: python3 scripts/audit.py blob - 0faa60f4ceb4969c7a30672887e9998487ddb22e blob + c6ac4c2c73d4f565c72ecbb0960402c38dc2a74c --- README.md +++ README.md @@ -1,2 +1,200 @@ # guix-channel +Canal personal de GNU Guix para el Nitro 5 — Richard Bernal Estrada. + +[![Audit](https://codeberg.org/Richard7987/guix-channel/actions/workflows/audit.yml/badge.svg)](https://codeberg.org/Richard7987/guix-channel/actions) +[![Version](https://img.shields.io/badge/sistema-v2026.1-blue?style=flat)](https://codeberg.org/Richard7987/guix-channel/releases) +[![Guix](https://img.shields.io/badge/GNU_Guix-1.5-orange?style=flat)](https://guix.gnu.org) +[![Licencia](https://img.shields.io/badge/licencia-GPL--3.0-green?style=flat)](LICENSE) + +Canal con paquetes binarios y configuración de sistema para el Acer Nitro 5 +(Intel UHD 630 + GTX 1050 Max-Q, PRIME Render Offload, KDE Plasma). + +--- + +## Estructura + +``` +guix-channel/ +├── .forgejo/workflows/ +│ └── audit.yml ← CI: verificación estática automática +├── richard/ +│ ├── packages/ +│ │ ├── zen-browser.scm ← Zen Browser 1.12.9b (binary wrap) +│ │ └── mullvad.scm ← Mullvad VPN 2026.1 (binary wrap desde .deb) +│ └── services/ +│ └── mullvad.scm ← Servicio Shepherd para mullvad-daemon +├── scripts/ +│ └── audit.py ← Script de verificación estática (58 checks) +└── system/ + ├── channels.scm ← Canales: guix + nonguix + este canal + ├── config.scm ← Configuración del sistema (/etc/config.scm) + └── home.scm ← Guix Home: GPG, YubiKey, bash +``` + +--- + +## Agregar el canal + +Añade esto a `~/.config/guix/channels.scm`: + +```scheme +(channel + (name 'richard) + (url "https://codeberg.org/Richard7987/guix-channel") + (branch "main") + (introduction + (make-channel-introduction + "17ca291dac7ec48ce8266b3726d1fdcc513e99f7" + (openpgp-fingerprint + "91CA 581F 7B78 01E8 8673 D228 DBD5 F61D 8A0A 14D7")))) +``` + +Luego: + +```bash +guix pull +guix install zen-browser # o mullvad-vpn +``` + +--- + +## Instalar el sistema completo (Nitro 5) + +```bash +# 1. Clonar el repo +git clone git@codeberg.org:Richard7987/guix-channel.git ~/guix-channel + +# 2. Copiar configuraciones +sudo cp ~/guix-channel/system/config.scm /etc/config.scm +mkdir -p ~/.config/guix +cp ~/guix-channel/system/channels.scm ~/.config/guix/channels.scm + +# 3. Actualizar canales y reconfigurar +guix pull +sudo guix system reconfigure /etc/config.scm + +# 4. Aplicar configuración de usuario (Guix Home) +guix home reconfigure ~/guix-channel/system/home.scm +``` + +--- + +## Paquetes incluidos + +### Zen Browser (`zen-browser`) + +Fork de Firefox enfocado en privacidad con barra lateral y espacios de trabajo. +Empaquetado como binary wrap desde el tarball oficial de GitHub. + +```bash +guix install zen-browser +``` + +Para actualizar a una versión nueva: + +```bash +# 1. Editar richard/packages/zen-browser.scm — cambiar 'version' +# 2. Obtener el hash nuevo: +guix download https://github.com/zen-browser/desktop/releases/download/VERSION/zen.linux-x86_64.tar.xz +# 3. Reemplazar el (base32 "...") con el hash obtenido +git commit -am "zen-browser: actualizar a VERSION" +git push +``` + +### Mullvad VPN (`mullvad-vpn` + servicio Shepherd) + +Cliente VPN centrado en privacidad. Incluye daemon (`mullvad-daemon`) +y CLI (`mullvad`). El daemon arranca automáticamente con el sistema. + +```bash +# Tras instalar el sistema, activar la cuenta: +mullvad account login TU_NUMERO_DE_CUENTA + +# Conectar +mullvad relay set location mx # servidores en México +mullvad connect + +# Estado +mullvad status +herd status mullvad +``` + +Para actualizar: + +```bash +# 1. Editar richard/packages/mullvad.scm — cambiar 'version' +# 2. Obtener el hash: +wget https://github.com/mullvad/mullvadvpn-app/releases/download/VERSION/MullvadVPN-VERSION_amd64.deb +sha256sum MullvadVPN-VERSION_amd64.deb | python3 scripts/nix32.py +# 3. Reemplazar el (base32 "...") con el resultado +``` + +--- + +## Hardware objetivo + +| Componente | Detalle | +|---|---| +| Laptop | Acer Nitro 5 | +| CPU | Intel Coffee Lake-H | +| iGPU | Intel UHD 630 (`PCI:0:2:0`) | +| dGPU | NVIDIA GTX 1050 3 GB Max-Q (`PCI:1:0:0`) | +| GPU Mode | PRIME Render Offload (sin MUX switch) | +| DE | KDE Plasma 6 + SDDM | +| Kernel | Linux no-libre (nonguix) | + +### Verificar PRIME tras instalar + +```bash +# Debe mostrar Intel/Mesa +glxinfo | grep "OpenGL renderer" + +# Debe mostrar NVIDIA GTX 1050 +__NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia \ + glxinfo | grep "OpenGL renderer" + +# Lanzar Blender con NVIDIA +__NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia blender +``` + +--- + +## Versionado + +Este proyecto usa **CalVer** (`YYYY.N`): + +| Versión | Fecha | Cambios | +|---|---|---| +| v2026.1 | Mayo 2026 | Versión inicial: KDE Plasma, PRIME Offload, Mullvad, Zen Browser, YubiKey | + +Para crear un nuevo release en Codeberg: + +```bash +git tag v2026.2 +git push origin v2026.2 +``` + +--- + +## CI — Verificación estática + +El script `scripts/audit.py` corre 58 checks automáticos en cada push: + +- Validez de hashes nix32 (formato y longitud) +- Imports de módulos requeridos en todos los archivos `.scm` +- Presencia de servicios críticos (`nvidia-service-type`, `sddm-service-type`, etc.) +- Configuración PRIME (`BusID`, `AllowNVIDIAGPUScreens`, `nvda`) +- Paquetes requeridos en el sistema +- Configuración de Guix Home (GPG, YubiKey, pinentry) + +```bash +# Correr localmente +python3 scripts/audit.py +``` + +--- + +## Licencia + +GPL-3.0 — ver [LICENSE](LICENSE) blob - /dev/null blob + f926fecfabb9fbedfa5976852ea563121a6b01f4 (mode 644) --- /dev/null +++ scripts/audit.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 +""" +audit.py — Verificación estática del canal Guix de Richard. +Ejecuta checks sobre módulos, hashes, imports y estructura. +Retorna exit code 0 si todo pasa, 1 si hay errores críticos. +""" + +import re +import sys +import os + +BASE = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + +def load(path): + with open(os.path.join(BASE, path)) as f: + return f.read() + +c = { + "cfg": load("system/config.scm"), + "chan": load("system/channels.scm"), + "home": load("system/home.scm"), + "zen": load("richard/packages/zen-browser.scm"), + "mul": load("richard/packages/mullvad.scm"), + "svc": load("richard/services/mullvad.scm"), +} + +NIX = set("0123456789abcdfghijklmnpqrsvwxyz") +def hash_ok(h): return len(h) == 52 and all(x in NIX for x in h) + +passed, failed = [], [] + +def ck(cond, label): + (passed if cond else failed).append(label) + +# ── channels.scm ──────────────────────────────────────────────── +ck("897c1a470da759236cc11798f4e0a5f7d4d59fbc" in c["chan"], "channels: nonguix intro hash") +ck("2A39 3FFF 68F4 EF7A" in c["chan"], "channels: nonguix fingerprint") +ck("git.savannah.gnu.org/git/guix.git" in c["chan"], "channels: guix URL oficial") +ck("Richard7987/guix-channel" in c["chan"], "channels: canal personal URL") +ck("17ca291dac7ec48ce8266b3726d1fdcc513e99f7" in c["chan"], "channels: canal personal intro commit") + +# ── packages/zen-browser.scm ──────────────────────────────────── +ck(hash_ok("0zjck0yqly6lbyj4njdjcj0p0fwv9k69lx4rwks53f72caqs95hs"), "zen: hash nix32 válido") +ck("(gnu packages base)" in c["zen"], "zen: import (gnu packages base)") +ck("(gnu packages elf)" in c["zen"], "zen: import (gnu packages elf)") +ck("LD_LIBRARY_PATH" in c["zen"], "zen: LD_LIBRARY_PATH en wrapper") +ck("MOZ_ENABLE_WAYLAND" in c["zen"], "zen: Wayland habilitado") +ck("zen-browser.desktop" in c["zen"], "zen: .desktop entry") +ck("license:mpl2.0" in c["zen"], "zen: licencia MPL-2.0") + +# ── packages/mullvad.scm ──────────────────────────────────────── +ck(hash_ok("0gpg5yb1b4fw6zw06ymgicw46v7qj4sf7i5zd5srdhqvn66rlmqy"), "mullvad: hash nix32 válido") +ck("(gnu packages binutils)" in c["mul"], "mullvad: import (gnu packages binutils)") +ck("data.tar.xz" in c["mul"] and "data.tar.zst" in c["mul"], "mullvad: detección xz+zst") +ck("copy-recursively app-src lib-dir" in c["mul"], "mullvad: copy-recursively (path con espacio)") +ck("--set-interpreter" in c["mul"], "mullvad: patchelf interpreter") +ck("--set-rpath" in c["mul"], "mullvad: patchelf rpath") +ck("license:gpl3+" in c["mul"], "mullvad: licencia GPL-3+") + +# ── services/mullvad.scm ──────────────────────────────────────── +ck("(gnu services)" in c["svc"], "svc: import (gnu services)") +ck("gnu services configuration" not in c["svc"], "svc: sin módulo incorrecto") +ck("lib/mullvad-vpn/mullvad-daemon" in c["svc"], "svc: path daemon correcto") +ck("(requirement '(networking nftables))" in c["svc"], "svc: requirement correcto") +ck("activation-service-type" in c["svc"], "svc: activation-service-type") +ck("(respawn? #t)" in c["svc"], "svc: respawn activado") + +# ── system/config.scm — imports ───────────────────────────────── +ck("(gnu services sddm)" in c["cfg"], "cfg: import (gnu services sddm)") +ck("(nongnu services nvidia)" in c["cfg"], "cfg: import (nongnu services nvidia)") +ck("(guix transformations)" in c["cfg"], "cfg: import (guix transformations)") +ck("(nongnu packages nvidia)" in c["cfg"], "cfg: import (nongnu packages nvidia)") +ck("(richard packages zen-browser)" in c["cfg"], "cfg: import richard/zen-browser") +ck("(richard services mullvad)" in c["cfg"], "cfg: import richard/services/mullvad") + +# ── system/config.scm — sistema ───────────────────────────────── +ck(bool(re.search(r'\(kernel\s+linux\)', c["cfg"])), "cfg: kernel linux (nonguix)") +ck("microcode-initrd" in c["cfg"], "cfg: microcode-initrd") +ck("linux-firmware" in c["cfg"], "cfg: linux-firmware") +ck("(kernel-loadable-modules (list nvidia-module))" in c["cfg"],"cfg: kernel-loadable-modules nvidia-module") +ck("modprobe.blacklist=nouveau" in c["cfg"], "cfg: blacklist nouveau") +ck("nvidia-drm.modeset=1" in c["cfg"], "cfg: nvidia-drm.modeset=1") +ck("grub-efi-bootloader" in c["cfg"], "cfg: GRUB EFI") + +# ── system/config.scm — servicios ─────────────────────────────── +ck("(service nvidia-service-type)" in c["cfg"], "cfg: nvidia-service-type") +ck("simple-service 'nvidia-udev" not in c["cfg"], "cfg: sin udev manual") +ck("plasma-desktop-service-type" in c["cfg"], "cfg: plasma-desktop-service-type") +ck("sddm-service-type" in c["cfg"], "cfg: sddm-service-type") +ck("(cons* nvda %default-xorg-modules)" in c["cfg"], "cfg: nvda en Xorg modules") +ck("mesa=nvda" in c["cfg"], "cfg: graft mesa→nvda") +ck("PCI:0:2:0" in c["cfg"], "cfg: BusID Intel UHD 630") +ck("PCI:1:0:0" in c["cfg"], "cfg: BusID GTX 1050") +ck("AllowNVIDIAGPUScreens" in c["cfg"], "cfg: PRIME AllowNVIDIAGPUScreens") +ck("(mullvad-service)" in c["cfg"], "cfg: mullvad-service") +ck("pcscd-service-type" in c["cfg"], "cfg: pcscd (YubiKey)") +ck("nftables-service-type" in c["cfg"], "cfg: nftables firewall") +ck("(delete gdm-service-type)" in c["cfg"], "cfg: GDM eliminado") +ck("zen-browser)" in c["cfg"], "cfg: zen-browser en packages") + +# ── system/home.scm ───────────────────────────────────────────── +ck("simple-service 'gpg-agent-conf home-files-service-type" in c["home"], "home: simple-service correcto") +ck('"pinentry"' in c["home"], "home: pinentry instalado") +ck(".guix-home/profile/bin/pinentry-curses" in c["home"], "home: path pinentry-curses") +ck("enable-ssh-support" in c["home"], "home: SSH support gpg-agent") +ck("GPG_TTY" in c["home"], "home: GPG_TTY en bashrc") +ck("SSH_AUTH_SOCK" in c["home"], "home: SSH_AUTH_SOCK en bashrc") + +# ── Resultado ──────────────────────────────────────────────────── +total = len(passed) + len(failed) +print(f"╔══════════════════════════════════════╗") +print(f"║ Guix Channel Audit — {total} checks ║") +print(f"╠══════════════════════════════════════╣") +print(f"║ ✅ Passed: {len(passed):>3} ❌ Failed: {len(failed):>3} ║") +print(f"╚══════════════════════════════════════╝") + +if failed: + print("\n❌ FAILED CHECKS:") + for f in failed: + print(f" ✗ {f}") + sys.exit(1) +else: + print("\n✅ All checks passed — ready to install!") + sys.exit(0)