diff --git a/modules/packs/README.md b/modules/packs/README.md new file mode 100644 index 0000000..f9ff41c --- /dev/null +++ b/modules/packs/README.md @@ -0,0 +1,46 @@ +# modules/packs + +Opt-in **packs** — bundles of (packages + services + config) toggled with +`omni.packs..enable`. This is the "core + goodies" layer: core is +always on; packs are off until you ask for them. + +Full guide (enabling, standalone import, authoring, bitcoin specifics, +verification): **[`docs/packs.md`](../../docs/packs.md)**. + +## Pattern + +Each pack is one self-contained module, **always imported but inert** until +enabled (hlissner-style enable-gate): + +```nix +{ config, lib, pkgs, ... }: +let cfg = config.omni.packs.media; in { + options.omni.packs.media.enable = lib.mkEnableOption "Media pack"; + config = lib.mkIf cfg.enable { environment.systemPackages = with pkgs; [ … ]; }; +} +``` + +## Files + +| File | Purpose | +|---|---| +| `default.nix` | Aggregator — imports every pack + `compat.nix`. Wired into the build once, via `lib/mksystem.nix`. The ISO bypasses mksystem, so it stays pack-free. | +| `compat.nix` | Back-compat bridge: maps legacy `omni.features.*` → `omni.packs.*.enable` (mkDefault). Aggregator-only, so standalone imports don't pull in `omni.features`. | +| `media.nix`, `development.nix`, `gaming.nix`, `office.nix`, `containers.nix` | Desktop-bundle packs (migrated from `packages.nix` categories + the feature-gated bits of `core.nix`/`development.nix`). Omnixient-coupled (use `omni.lib.filterPackages`). | +| `lnbits.nix` | Wraps `../dev-env` and enables it. **Standalone-importable** (dev-env is decoupled from `omni.*`). | +| `aiolabs.nix` | Imports the gated aiolabs preset (`../dev-env/presets/aiolabs.nix`) and pulls in `lnbits`. **Standalone-importable.** | +| `bitcoin.nix` | nix-bitcoin node (bitcoind + clightning). **NOT in the aggregator** — nix-bitcoin's module asserts on import even when disabled; exposed as `nixosModules.bitcoin` for explicit per-host import. | + +## Exposed as flake outputs + +`flake.nixosModules.{media,development,gaming,office,containers,lnbits, +aiolabs,bitcoin}` — reusable across a second host (`gizmo`) and third +parties. `lnbits`/`aiolabs`/`bitcoin` work on a non-Omnixient NixOS. + +## Adding a pack + +See [`docs/packs.md` → Authoring a new pack](../../docs/packs.md#authoring-a-new-pack). +In short: copy the template, register in `default.nix` (unless it has +import-time side effects), expose in `flake.nix`, keep it +`config.omni.`-free if it should be standalone, and verify the +omni closure is unchanged with `nix store diff-closures`. diff --git a/modules/packs/compat.nix b/modules/packs/compat.nix new file mode 100644 index 0000000..f50c47a --- /dev/null +++ b/modules/packs/compat.nix @@ -0,0 +1,25 @@ +# Back-compat bridge — maps the legacy omni.features.* booleans onto the +# new omni.packs.*.enable toggles via mkDefault, so existing hosts and +# the `preset` enum keep working unchanged through (and after) the +# migration. A host can still override any omni.packs..enable +# explicitly because these are mkDefault. +# +# Lives in the packs aggregator (modules/packs/default.nix), which is only +# loaded as part of a full omni system via lib/mksystem.nix — so a +# standalone consumer importing a single pack module (e.g. +# nixosModules.lnbits) never pulls in this omni.features dependency. +{ config, lib, ... }: +let + cfg = config.omni; +in +{ + config = lib.mkIf (cfg.enable or false) { + omni.packs = { + media.enable = lib.mkDefault (cfg.features.media or false); + gaming.enable = lib.mkDefault (cfg.features.gaming or false); + office.enable = lib.mkDefault ((cfg.features.office or false) || (cfg.features.communication or false)); + containers.enable = lib.mkDefault (cfg.features.containers or false); + development.enable = lib.mkDefault (cfg.features.coding or false); + }; + }; +} diff --git a/modules/packs/containers.nix b/modules/packs/containers.nix new file mode 100644 index 0000000..b6e4b03 --- /dev/null +++ b/modules/packs/containers.nix @@ -0,0 +1,43 @@ +# Containers pack — Docker + Podman. +# +# Unifies the docker config that was previously split between core.nix +# (basic enable + weekly autoPrune) and development.nix (daemon.settings +# buildkit + registry-mirror + autoPrune --all), plus the podman block +# that lived coding-gated in development.nix. Now a single source of truth +# gated on omni.packs.containers.enable. (The merged result is the union +# of the two old blocks — identical on any host that had both features on, +# e.g. omni.) +{ config, lib, ... }: +let + cfg = config.omni.packs.containers; +in +{ + options.omni.packs.containers.enable = + lib.mkEnableOption "Containers pack (Docker + Podman)"; + + config = lib.mkIf cfg.enable { + virtualisation.docker = { + enable = true; + enableOnBoot = true; + daemon.settings = { + features = { + buildkit = true; + }; + registry-mirrors = [ "https://mirror.gcr.io" ]; + }; + + autoPrune = { + enable = true; + dates = "weekly"; + flags = [ "--all" ]; + }; + }; + + # Podman as Docker alternative (dockerCompat off to avoid conflict). + virtualisation.podman = { + enable = true; + dockerCompat = false; + defaultNetwork.settings.dns_enabled = true; + }; + }; +} diff --git a/modules/packs/default.nix b/modules/packs/default.nix new file mode 100644 index 0000000..ee1f02e --- /dev/null +++ b/modules/packs/default.nix @@ -0,0 +1,33 @@ +# omni packs — opt-in bundles of (packages + services + config). +# +# Every pack module is ALWAYS imported but inert until +# `omni.packs..enable = true` (hlissner-style enable-gate), so +# the option namespace is always declared and discoverable while nothing +# is built unless asked for. This aggregator is wired into the build at a +# single point — lib/mksystem.nix — so the ISO path (a direct nixosSystem +# call that bypasses mksystem) stays pack-free. +# +# The lnbits / aiolabs / bitcoin packs are standalone-importable: they +# declare their own option namespace and touch only standard NixOS +# options + their own bundled modules, so a third party can import e.g. +# `nixosModules.lnbits` on their own NixOS without enabling omni core. +{ ... }: +{ + imports = [ + ./compat.nix + ./media.nix + ./development.nix + ./gaming.nix + ./office.nix + ./containers.nix + ./lnbits.nix + ./aiolabs.nix + # bitcoin.nix is deliberately NOT in this always-loaded aggregator: + # nix-bitcoin's default module fires a secrets assertion just from + # being imported (even with no services enabled), so importing it + # inert on every host breaks eval. It's exposed as + # `nixosModules.bitcoin` instead — a host that wants a node imports it + # explicitly and sets omni.packs.bitcoin.enable. (inputs.nix-bitcoin + # is provided to such hosts via mksystem specialArgs.) + ]; +} diff --git a/modules/packs/development.nix b/modules/packs/development.nix new file mode 100644 index 0000000..d7aba1f --- /dev/null +++ b/modules/packs/development.nix @@ -0,0 +1,109 @@ +# Development pack — editors, language servers, compilers, build tools, +# container CLIs, DB clients, cloud tooling, plus git/npm programs and dev +# manpages. +# +# Migrated from packages.nix `development` category + the coding-gated +# bits of core.nix (programs.git/npm, documentation.dev, gcc/gnumake). +# The richer dev module (modules/development.nix: shells, services, +# helper scripts) is re-gated onto omni.packs.development.enable. +{ config, lib, pkgs, ... }: +let + cfg = config.omni.packs.development; +in +{ + options.omni.packs.development.enable = + lib.mkEnableOption "Development pack (editors, LSPs, compilers, build tools, container CLIs)"; + + config = lib.mkIf cfg.enable { + documentation.dev.enable = true; + + programs.git = { + enable = true; + lfs.enable = true; + }; + programs.npm.enable = true; + + environment.systemPackages = config.omni.lib.filterPackages ( + with pkgs; + [ + # Editors and IDEs + # neovim (configured via home-manager programs.neovim) + emacs + vscode + jetbrains.idea-oss + + # Language servers + typescript-language-server + vscode-langservers-extracted + rust-analyzer + gopls + pyright + lua-language-server + clang-tools + + # Debuggers + gdb + lldb + delve + + # Build tools + gnumake + cmake + meson + ninja + autoconf + automake + libtool + pkg-config + + # Compilers and interpreters + gcc + clang + rustc + cargo + go + python3 + nodejs + deno + bun + + # Container tools + docker + docker-compose + podman + buildah + skopeo + kind + kubectl + kubernetes-helm + k9s + + # Database clients + postgresql + mariadb + sqlite + redis + mongodb-tools + dbeaver-bin + + # API testing + httpie + curl + postman + insomnia + + # Cloud tools + awscli2 + google-cloud-sdk + azure-cli + terraform + ansible + + # Documentation + mdbook + hugo + zola + ] + ); + }; +} diff --git a/modules/packs/gaming.nix b/modules/packs/gaming.nix new file mode 100644 index 0000000..dd77897 --- /dev/null +++ b/modules/packs/gaming.nix @@ -0,0 +1,33 @@ +# Gaming pack — Steam, Lutris, Wine, performance tools. +# Migrated from packages.nix `gaming` category + the steam block in core.nix. +{ config, lib, pkgs, ... }: +let + cfg = config.omni.packs.gaming; +in +{ + options.omni.packs.gaming.enable = + lib.mkEnableOption "Gaming pack (Steam, Lutris, Wine, performance tools)"; + + config = lib.mkIf cfg.enable { + programs.steam = { + enable = true; + remotePlay.openFirewall = true; + dedicatedServer.openFirewall = true; + }; + + environment.systemPackages = config.omni.lib.filterPackages ( + with pkgs; + [ + steam + lutris + wine + winetricks + protonup-rs + mangohud + gamemode + discord + obs-studio + ] + ); + }; +} diff --git a/modules/packs/media.nix b/modules/packs/media.nix new file mode 100644 index 0000000..ab87d37 --- /dev/null +++ b/modules/packs/media.nix @@ -0,0 +1,84 @@ +# Media pack — players, image/video editing, screen capture. +# +# Migrated from packages.nix `multimedia` category. Runs the list through +# omni.lib.filterPackages so the omni.packages.exclude mechanism still +# applies — this is a desktop-bundle pack (omni-coupled by design), not +# one of the standalone-importable packs. +{ config, lib, pkgs, ... }: +let + cfg = config.omni.packs.media; +in +{ + options.omni.packs.media.enable = + lib.mkEnableOption "Media pack (players, image/video editing, screen capture)"; + + config = lib.mkIf cfg.enable { + environment.systemPackages = config.omni.lib.filterPackages ( + with pkgs; + [ + # Audio + pipewire + pulseaudio + pavucontrol + easyeffects + spotify + spotifyd + cmus + mpd + ncmpcpp + + # Video + mpv + vlc + obs-studio + kdePackages.kdenlive + handbrake + ffmpeg-full + + # Images + imv + feh + gimp + inkscape + krita + imagemagick + graphicsmagick + drawio + + # Image morphing (python + opencv + dlib for landmark-based morphing). + # Exposed as `morph-py` so it doesn't collide with the bare `python3` + # pulled in by the development category. + (writeShellScriptBin "morph-py" '' + exec ${ + python3.withPackages ( + ps: with ps; [ + opencv4 + dlib + face-recognition-models + numpy + scipy + ] + ) + }/bin/python3 "$@" + '') + + # 3D / CAD — bare `openscad` is pinned to 2021.01 which no + # longer builds against current toolchains in nixpkgs-unstable. + openscad-unstable + + # Screen capture + grim + slurp + wf-recorder + flameshot + peek + + # PDF + zathura + evince + kdePackages.okular + mupdf + ] + ); + }; +} diff --git a/modules/packs/office.nix b/modules/packs/office.nix new file mode 100644 index 0000000..2860237 --- /dev/null +++ b/modules/packs/office.nix @@ -0,0 +1,76 @@ +# Office pack — browsers, communication, office suite, notes, password +# managers, sync/backup. +# +# Migrated from packages.nix `productivity` category, which is gated on +# features.office OR features.communication today; this pack reproduces +# the whole list to preserve parity (splitting office vs communication is +# a follow-up). Run through omni.lib.filterPackages so exclude applies. +{ config, lib, pkgs, ... }: +let + cfg = config.omni.packs.office; +in +{ + options.omni.packs.office.enable = + lib.mkEnableOption "Office pack (browsers, comms, office suite, notes, backup)"; + + config = lib.mkIf cfg.enable { + environment.systemPackages = config.omni.lib.filterPackages ( + with pkgs; + [ + # Browsers + firefox + chromium + brave + qutebrowser + + # Communication + # discord + # slack + # telegram-desktop + signal-desktop + element-desktop + ferdium + # zoom-us + # teams-for-linux + + # Bitcoin + sparrow + + # Office + libreoffice + onlyoffice-desktopeditors + wpsoffice + + # Note taking + obsidian + # logseq + # joplin-desktop + # zettlr + + # Spaced repetition / learning + anki + + # Email + # thunderbird + # aerc + # neomutt + + # Calendar + calcurse + khal + + # Password managers + bitwarden-desktop + keepassxc + pass + + # Sync and backup + syncthing + nextcloud-client + rclone + restic + borgbackup + ] + ); + }; +}