On 5/19/25 00:24, James Thomas wrote: > Naranden writes: >> On 5/16/25 04:14, James Thomas wrote: >>> Naranden writes: >>>> I suppose there must be some way to make this work like Guix system >>>> containers, where everything the container needs is loaded from the >>>> store rather than through Docker. >>> >>> Why not build the 'container' script for the users and let them run it? >> >> I'm not sure what you mean. The goal isn't to ship to other users but >> to declare a specific, reproducible operating-system with services >> that can be deployed on a local (real) system, in a VM, or remotely. >> More specifically, the goal is to include a guix system container >> service in an operating-system definition--in other words, > >> a Guix operating-system (container) nested in another operating-system >> (parent). > > That's what running the script of ‘container’ in (info "(guix) Invoking > guix system") gets you, no?
Yes, running the script written by `guix system container` does provide a Guix operating-system container on the local system. But the system must have a read-write /gnu/store and be capable of building/acquiring the dependencies. For example, it does not work for guix system vm, which uses a read-only /gnu/store. (See example 1 below.) > No new 'service' should be required. The goal is to get something managed by Shepherd (so it is started at boot, is automatically respawned, etc.). That's why a service is required (unless there is some other way to accomplish those things). See example 2 below. Also I found a project that seems to maybe have a similar goal, but there hasn't been any activity there since about 1.5 years ago: https://github.com/BIMSBbioinfo/swineherd >> 1. I can bundle a package (and its dependencies) and run a command in a >> container with `guix shell --container $package -- run`. Can I set up >> the same thing to happen as a Shepherd-managed service (in an >> operating-system definition)? >> >> 2. And if that can be done, can I set the channels and use package >> inferiors so I would get the equivalent of `guix time-machine -C >> $channels -- shell ...` but in a Shepherd-managed service as in (1)? >> >> 3. And if *that* can be done, can I do the same with an entire nested >> operating-system as in my original question and example?! That is, >> equivalent to `guix time-machine -C $channels -- system vm $file` but as >> a Shepherd-managed service nested inside a parent operating-system >> definition, where the parent operating-system definition could itself be >> executed in a VM with `guix time-machine -C $channels -- system vm >> $file`. (It's amazing that this level of reproducibility might actually >> be possible with Guix.) > > AFAIU your requirements, they're possible with the shepherd-transient > service and 'guix time-machine' prefixing the command mentioned above. I looked at transient services but from what I understand they don't run on boot (only the parent transient-service does). It just allows the user to run transient services during run-time. I am trying to run something at boot, managed by Shepherd. ====================================================================== Example 1: Trying to use `guix system container` in a VM os.scm: ``` (use-modules (gnu)) (operating-system (host-name "os") (file-systems (cons (file-system (device (file-system-label "does-not-matter")) (mount-point "/") (type "ext4")) %base-file-systems)) (bootloader (bootloader-configuration (bootloader grub-bootloader)))) ``` In the shell: ``` $ $(guix system --no-graphic vm os.scm) -m 1G ## Log in as root # nano os.scm ## Write the above `os.scm` file inside the VM # guix system container os.scm guix system: error: changing ownership of path '/gnu/store': Read-only file system ``` ====================================================================== Example 2: mlauncher (manifest launcher) service This shows implementation and use of a rudimentary service that: - is managed by Shepherd, - uses a profile defined by a package manifest, and - runs a specified command using that profile. However: - there is no Linux container or other isolation and - it does not accept a Guix operating-system definition. In the context of this discussion, it may be reasonable to skip the "Implementing" part and go to the "Using" part. I have not found out a way to use something like the output of `(gnu build linux-container)` module's `(container-script os)` in `mlauncher-shepherd-service` below to get a container as provided by `guix system container`. os.scm: ``` (use-modules (gnu bootloader)) (use-modules (gnu bootloader grub)) (use-modules (gnu packages)) (use-modules (gnu services base)) (use-modules (gnu services shepherd)) (use-modules (gnu system file-systems)) (use-modules (guix gexp)) (use-modules (guix profiles)) (use-modules (guix records)) ;; Implementing the service. (define-record-type* <mlauncher-configuration> mlauncher-configuration make-mlauncher-configuration mlauncher-configuration? (command mlauncher-configuration-command) (manifest mlauncher-configuration-manifest) (name mlauncher-configuration-name)) (define (mlauncher-shepherd-service config) "Return a <shepherd-service> for mlauncher with CONFIG." (define mlauncher-command (cons* (file-append (profile (content (mlauncher-configuration-manifest config))) (car (mlauncher-configuration-command config))) (cdr (mlauncher-configuration-command config)))) (list (shepherd-service (documentation "mlauncher service") (provision (list (string->symbol (string-append "mlauncher-" (mlauncher-configuration-name config))))) (requirement '(syslogd)) (start #~(make-forkexec-constructor '#$mlauncher-command))))) (define mlauncher-service-type (service-type (name 'mlauncher) (extensions (list (service-extension shepherd-root-service-type mlauncher-shepherd-service))) (description "Run a command in a profile defined by a manifest."))) ;; Using the service. (define test-manifest (specifications->manifest (list "python-minimal"))) (define test-mlauncher-service (service mlauncher-service-type (mlauncher-configuration (command (list "/bin/python3" "-c" "import sys,time;print('hi',file=sys.stderr);time.sleep(60)")) (manifest test-manifest) (name "test")))) (define runner-mlauncher-service (service mlauncher-service-type (mlauncher-configuration (command (list "/bin/runner")) (manifest test-manifest) (name "runner")))) (operating-system (host-name "host-os") (file-systems (cons (file-system (device (file-system-label "does-not-matter")) (mount-point "/") (type "ext4")) %base-file-systems)) (bootloader (bootloader-configuration (bootloader grub-bootloader))) (services (cons* test-mlauncher-service %base-services))) ``` In the shell: ``` $ $(guix system --no-graphic vm os.scm) -m 1G ## Log in as root # herd status mlauncher-test ● Status of mlauncher-test: It is running since 07:14:51 PM (38 seconds ago). Main PID: 105 Command: /gnu/store/yf4k9v2kw3hcy2567pf30m3r2l4800gc-profile/bin/python3 -c "import sys,time;print('hi',file=sys.stderr);time.sleep(60)" It is enabled. Provides: mlauncher-test Requires: syslogd Will be respawned. Recent messages (use '-n' to view more or less): 2025-05-21 19:14:52 hi ``` ====================================================================== I appreciate your feedback. Thanks, Naranden
