Andrew schrieb am Donnerstag der 23. Dezember 2021 um 16:16 +03:
But what is the preference between a list and an alist? Why does
and ‘home-file-service-type’ use
Toggle quote (21 lines)
>>> +There is a module @code{gnu service configuration}, which contains
>>> +helpers simplifying configuration definition process. Take a look at
>>> +@code{gnu services docker} module or grep for
>>> +@code{define-configuration} to find usage examples.
>>> +@c Provide some examples, tips, and rationale behind @code{gnu service
>>> +@c configuration} module.
>> Note that I already sent a patch that (at least tries to) document (gnu
>> service configuration)[1].
>> One thing that is lacking is when to use (guix records) (which isn’t
>> documented yet) vs (gnu service configuration). There should probably
>> be one or two paragraphs about that.
> Saw it, I'll try to review and comment on it, when I'll get some spare
> time. I'll keep this comment for now, and after the section about gnu
> service configuration module is merged, we will add links to it and
> provide more info and examples on implementing actual configurations.
It has already been merged now. :-)
I suggested adding a footnote for the meaning of “kebab-case”. I don’t
think these examples should just be in a footnote. Footnotes are
usually used for stuff that might be distracting if put in the text; I
wouldn’t consider these examples distracting; they are very valuable.
That’s why we have documentation for all the fields. Moreover, if it
wasn’t documented, the order of the contents of the fields of
‘home-bash-configuration’ aren’t obvious to the user either.
That applies for the Bash service as well; it unconditionally adds stuff
Toggle quote (36 lines)
> For nginx it's only partially true, you actually can use `file` field,
> but it will alter the effect of all other fields and will just use the
> file as nginx.conf, kinda conforms what I'm asking here, but makes all
> Added the following explanation to this item:
> --8<---------------cut here---------------start------------->8---
> For example, setting @code{guix-defaults?} to
> @code{#f} and @code{aliases} to @code{'()} will give user an ability to
> control the content of @file{.bashrc} solely by setting the value of
> --8<---------------cut here---------------end--------------->8---
>> It doesn’t mention if a configuration record should cover all the
>> configuration options available in a configuration file. For example,
>> the current ‘openssh-configuration’ has quite a few options, but these
>> obviously don’t cover all the options available in /etc/ssh/sshd_config,
>> which is why there is an “escape hatch”, ‘extra-content’ field.
>> In some cases a program might have too many configuration fields for us
>> to map using configuration records, e.g., Git. In rde, the approach we
>> took was to use nested lists to represent the INI configuration. I
>> think this approach could also be mentioned here.
> This is mentioned below, as well as the problem of closed-world
> assumption. Software should be fully configurable with field for
> respective config file, escape hatch should be a part of this field.
> Escape hatch is necessary to allow to reuse already existing
> configuration, but not to provide configuration, which can't be
> expressed by respective configuration field.
But the Git service in rde uses a ‘config-extra-content’ field, which is
basically the same thing as ‘extra-content’ or ‘extra-config’, right?
I don’t think it is grammatically correct to not put an object after
Toggle quote (19 lines)
>>> +configuration and resulting app config, including different field
>>> +casing, new semantic units.
>> But it means that the syntax for configuring a program is more
>> Scheme-like. For example, the Dovecot service provides a very
>> complicated but Schemeish interface for configuring Dovecot, though as
>> you have mentioned, it might be missing some fields since the Dovecot
>> configuration file might have changed since the creation of the service.
> Yes it is more Scheme-flavored, but it doesn't mean good. I can write a
> good rationale on this topic, but will do it next time, now I'll just
> give you an example, which should be relevant to you: Imagine writing an
> importer (for `guix home import` for example) from XML to SXML, now
> imagine that instead of SXML we have Scheme-like configuration. It
> hours and days more work. Implementing and maintaining such
> Scheme-flavored configuration is a big pain, especially if software
> still changes and config options isn't stable yet.
Sorry for being unclear, I meant that the docs were very one-sided and
only mentioned the advantages, and not the disadvantages. It should,
IMO, give a more objective view of problem.
Then it should be clearly stated that it currently doesn’t exist in
A few minutes later, Andrew wrote:
Toggle quote (88 lines)
> * guix.texi (Writing Service Configuration): New section.
> doc/guix.texi | 252 +++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 248 insertions(+), 4 deletions(-)
> diff --git a/doc/guix.texi b/doc/guix.texi
> index 333cb4117a..29d85d3dc5 100644
> @@ -10363,6 +10363,7 @@ compiling modules. It can be @code{#f}, @code{#t}, or @code{'detailed}.
> The other arguments are as for @code{derivation} (@pxref{Derivations}).
> +@anchor{file-like objects}
> @cindex file-like objects
> The @code{local-file}, @code{plain-file}, @code{computed-file},
> @code{program-file}, and @code{scheme-file} procedures below return
> @@ -15942,6 +15943,7 @@ symlink:
> Return a service that sets the host name to @var{name}.
> +@anchor{console-font-service-type}
> @defvr {Scheme Variable} console-font-service-type
> Install the given fonts on the specified ttys (fonts are per
> virtual console on the kernel Linux). The value of this service is a list of
> @@ -33717,6 +33719,7 @@ a daemon that can execute application bundles (sometimes referred to as
> +@anchor{docker-configuration}
> @deftp {Data Type} docker-configuration
> This is the data type representing the configuration of Docker and Containerd.
> @@ -35652,10 +35655,11 @@ them in an @code{operating-system} declaration. But how do we define
> them in the first place? And what is a service anyway?
> -* Service Composition:: The model for composing services.
> -* Service Types and Services:: Types and services.
> -* Service Reference:: API reference.
> -* Shepherd Services:: A particular type of service.
> +* Service Composition:: The model for composing services.
> +* Service Types and Services:: Types and services.
> +* Writing Service Configurations:: A guideline for writing guix services.
> +* Service Reference:: API reference.
> +* Shepherd Services:: A particular type of service.
> @node Service Composition
> @@ -35851,6 +35855,245 @@ There can be only one instance of an extensible service type such as
> Still here? The next section provides a reference of the programming
> interface for services.
> +@node Writing Service Configurations
> +@subsection Writing Service Configurations
> +Guix already contains a wide variety of system and home services, but
> +sometimes users might want to add new services. This section contains
> +tips for simplifying this process, and should help to make service
> +configurations and their implementations more consistent.
> +If you find any exceptions or patterns missing in this section, please
> +send a patch with additions/changes to @email{guix-devel@@gnu.org}
> +mailing list or just start a discussion/ask a question.
> +@subsubheading Configuration Itself
> +As we know from previous sections, a Guix service can accept a service
> +value, usually some kind of configuration record and optionally, be
> +extended with additional values by other services (@pxref{Service
> +When being extended, most services take some kind of configuration
> +record or a list thereof, but in some cases a simpler value is all
> +There are some cases, when the service accepts a list of pairs or some
> +other non-record values. For example, @code{console-font-service-type}
> +(@pxref{console-font-service-type}) accepts an
> +association list, and @code{etc-service-type} (@pxref{etc-service-type})
> +accepts a list of lists. Those services are kinda special, they do
> +auxiliary work of setting up some part of the operating system or home
> +environment, or just an intermediate helpers used by other Guix
> +services. For example @code{etc-service-type} is not that useful on its
> +own, but it helps other services to create files in /etc directory, when
Use @file{/etc} instead of just /etc.
Since the docs for (gnu services configuration) already exists, a link
pointing to the node should be used.
Just to make things clear, it would be preferable to call the field
‘git’ instead of ‘package’ even if there is only one packages that will
Toggle quote (32 lines)
> +Fields for configuration files, should be name the same as target
> +configuration file name, but in kebab-case@footnote{The case used for
> +identifiers in languages of Lisp family, example:
> +@code{this-is-kebab-case}.}: @code{bashrc} for @file{.bashrc},
> +@code{bash-profile} for @file{.bash_profile},
> +@code{tmux-conf} for @file{tmux.conf}, etc. The implementation
> +for such fields will be discussed in the next subsubsection.
> +Other fields in most cases add some boilerplates/reasonable defaults to
> +configuration files, enable/disable installation of some packages or
> +provide other custom behavior, for example @code{guix-defaults?} or
> +@code{aliases} fields in @code{home-bash-configuration}
> +(@pxref{home-bash-configuration}). There is no any special requirements
> +or recommendations here, but it's necessary to make it possible to
> +disable all the effects of such fields to provide a user with an empty
> +configuration and let them generate it from scratch with only field for
> +configuration file. For example, setting @code{guix-defaults?} to
> +@code{#f} and @code{aliases} to @code{'()} will give user an ability to
> +control the content of @file{.bashrc} solely by setting the value of
> +@subsubheading Fields for Configuration Files
> +The field should accept a data structure (preferably a combination of
> +simple lists, alists, @ref{Vectors, vectors,, guile,},
> +@ref{G-Expressions, gexps} and basic data types), which will be
> +serialized to target configuration format, in other words, it should
A link or footnote for “closed-world assumption” should be provided.
“…with the configuration options of the program, and it will make it…”
Toggle quote (35 lines)
> +ad-hoc and hard to reuse among other services with the same target
> +Exceptions can exist, but the overall idea is to provide a lispy syntax
> +for target configuration. Take a look at Sway example configuration
> +(which also can be used for i3). The following value of @code{config}
> +field of @code{home-sway-configuration}:
> +`((include ,(local-file "./sway/config"))
> + (bindsym $mod+Ctrl+Shift+a exec emacsclient -c --eval "'(eshell)'")
> + (bindsym $mod+Ctrl+Shift+o "[class=\"IceCat\"]" kill)
> + (input * ((xkb_layout us,ru)
> + (xkb_variant dvorak,))))
> +would yield something like:
> +include /gnu/store/408jwvh6wxxn1j85lj95fniih05gx5xj-config
> +bindsym $mod+Ctrl+Shift+a exec emacsclient -c --eval '(eshell)'
> +bindsym $mod+Ctrl+Shift+o [class="IceCat"] kill
> +The mapping between Scheme code and resulting configuration is quite
> +obvious. The serialization code with some type and structure checks
> +takes less than 70 lines and every possible Sway/i3 configuration can be
> +expressed using this field.
> +@subsubheading Let User Escape
Toggle quote (33 lines)
> +sure that it is possible to reuse it directly without rewriting. In the
> +example above, the following snippet allows one to include already an
> +existing config to the newly generated one utilizing @code{include}
> +directive of i3/Sway config language:
> +(include ,(local-file "./sway/config"))
> +When building a resulting config the file-like objects are substituted
> +with a path of the file in the store and Sway's @code{include} loads
> +this file during startup. The way file-like objects are treated here
> +also allows one to specify paths to plugins or other binary files like:
> +(load-plugin ,(file-append plugin-package "/share/plugin.so"))
> +(the example value for imaginary service configuration config file
> +In some cases the target configuration language may not have such an
> +@code{include} directive and can't provide such a functionallity, to
> +workaround it we can do the following trick:
> +#~(call-with-input-file
> + #$(local-file "./sway/config")
> + (@@ (ice-9 textual-ports) get-string-all))
> +The ‘get-string-all’ procedure will read the contents of the
Toggle quote (26 lines)
> +@file{./sway/config} file (to be more preciese the copy of this file
> +placed in the store), and return a string containing the contents. Once
> +serialized, the G-expression will thus be turn into the contents of the
> +Sway configuration file in @file{./sway/config}. This code can be
> +easily combined with the rest of Sway's configuration, additionally, we
> +can control the place where the content of @file{./sway/config} will
> +appear in resulting file by moving this snippet around.
> +Following these simple rules will help to make simple, consistent and
> +maintainable service configurations, and will let users express any
> +possible needs and reuse existing configuration files.
> @node Service Reference
> @subsection Service Reference
> @@ -36076,6 +36319,7 @@ The type of the ``boot service'', which produces the @dfn{boot script}.
> The boot script is what the initial RAM disk runs when booting.
> +@anchor{etc-service-type}
> @defvr {Scheme Variable} etc-service-type
> The type of the @file{/etc} service. This service is used to create
> files under @file{/etc} and can be extended by
Another point that might be worth bringing up is what we should do with
existing services which do not adhere to these guidelines. Should we
re-write them or just keep them as-is?
Sorry for the long delay! I will take a look at the “Return back
original implementation for text-config serialization” thread soon.