# Proposal to make guix system deployment more flexible TLDR: Make `(operating-system)` into a "derivation capable of storing data" that can be triggered using a function `(guix-build-system)` to enable more flexible system management ### Context and end-goal I am trying to port my NixOS managing system (https://git.dotya.ml/OpenVolt/nyxtumops) on guix to manage my systems where the expected goal is to be able to use public git repository to manage +200 systems at once through Continuous Integration and Delivery transparently to the user to provide https://snopyta.org -like libre service provider on a federated network to which new members can be added. To do this i've defined a programming logic that separates the configuration per hostname and domain with file hierarchy applying configuration further by defining: 1. Global -- Configuration is applies to all systems using the solution e.g. /users/kreyren.scm is expected to set user kreyren to all systems 2. Domain-wide -- Configuration applied only to the defined domain e.g. /domains//default.scm is expected to define configuration for the defined domain 3. Specific to the system -- Applied only to specified system e.g. domains//machines//default.scm is expected to define configuration only for the defined system See the repository on https://git.dotya.ml/RiXotStudio/grilumops ### The issue The currently used `(operating-system)` is basically a function with a lot of inputs with hard dependency on: - bootloaders - host-name - file-systems - timezone Making it impossible to define a modular and expression independent solution through `(load)`-ing the files e.g. Using command `guix system build src/default.scm` to execute following instructions: ``` ──────────────────────────────────── │ File: src/default.scm ──────────────────────────────────── ... 4 │ ;;; This file is the gateway in the system managing solution ,,, 16 │ (load "users/kreyren.scm") 17 │ (load "domains/rixotstudio.cz/default.scm") 18 │ 19 │ (display "Finished")(newline) ``` Where the `(load "users/kreyren.scm") is important as the file is expected to define a `kreyren` user across all systems which is not possible on the current handling to do in modular and expression independent way as: #### 1. Requires hard-written definition ```scm ;; First file (define-public kreyren (name "kreyren")...) ;; Second file (operating-system (users (user-account (source kreyren)))) ``` Which breaks modularity as one file can't be used in different parts of the source code and is expression-dependent as it requires hard-written `(source kreyren)` #### 2. Requires variable-driven layer ```scm ;; First file (define-public my-username "kreyren") ... ;; Second file (operating-system (users (user-account (name my-username))))) ``` which increases the complexity to the point where it significantly influences maintenance #### 3. Defining a solution that constructs the (operating-system) ```scm ``` which increases the complexity to the point where the managing solution is unmaintainable and impossible to expand on in terms of features ### Proposed solution Define `(operating-system)` into a "data-type capable of manipulating it's stored data" e.g. list, structure, etc.. and a function e.g. `(guix-build-system)` that reads the data from `(operating-system)` and applies it into a system build