aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/guix.texi73
-rw-r--r--gnu/services/base.scm75
2 files changed, 147 insertions, 1 deletions
diff --git a/doc/guix.texi b/doc/guix.texi
index 359c9b7a47..9a6a653d86 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -113,7 +113,7 @@ Copyright @copyright{} 2022 Bruno Victal@*
Copyright @copyright{} 2022 Ivan Vilata-i-Balaguer@*
Copyright @copyright{} 2023 Giacomo Leidi@*
Copyright @copyright{} 2022 Antero Mejr@*
-Copyright @copyright{} 2022 Bruno Victal@*
+Copyright @copyright{} 2023 Bruno Victal@*
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
@@ -40473,6 +40473,77 @@ In this example, the effect would be to add an @file{/etc/issue} file
pointing to the given file.
@end defvar
+@defvar hosts-service-type
+Type of the service that populates the entries for (@file{/etc/hosts}).
+This service type can be extended by passing it a list of
+@code{host} records.
+
+@c TRANSLATORS: The domain names below SHOULD NOT be translated.
+@c They're domains reserved for use in documentation. (RFC6761 Section 6.5)
+@c The addresses used are explained in RFC3849 and RFC5737.
+@lisp
+(simple-service 'add-extra-hosts
+ hosts-service-type
+ (list (host "192.0.2.1" "example.com"
+ '("example.net" "example.org"))
+ (host "2001:db8::1" "example.com"
+ '("example.net" "example.org"))))
+@end lisp
+
+@quotation Note
+@cindex @file{/etc/host} default entries
+By default @file{/etc/host} comes with the following entries:
+@example
+127.0.0.1 localhost @var{host-name}
+::1 localhost @var{host-name}
+@end example
+
+For most setups this is what you want though if you find yourself in
+the situation where you want to change the default entries, you can
+do so in @code{operating-system}.@pxref{operating-system Reference,@code{essential-services}}
+
+The following example shows how one would unset @var{host-name}
+from being an alias of @code{localhost}.
+@lisp
+(operating-system
+ ;; @dots{}
+
+ (essential-services
+ (modify-services
+ (operation-system-default-essential-services this-operating-system)
+ (hosts-service-type config => (list
+ (host "127.0.0.1" "localhost")
+ (host "::1" "localhost"))))))
+@end lisp
+@end quotation
+
+@deftp {Data Type} host
+Available @code{host} fields are:
+
+@table @asis
+@item @code{address} (type: string)
+IP address.
+
+@item @code{canonical-name} (type: string)
+Hostname.
+
+@item @code{aliases} (default: @code{'()}) (type: list-of-string)
+Additional aliases that map to the same @code{canonical-name}.
+
+@end table
+@end deftp
+
+@defun host address canonical-name [aliases]
+Procedure for creating @code{host} records.
+@end defun
+
+@quotation Note
+The @code{host} data type constructor is @code{%host} though it is
+tiresome to create multiple records with it so in practice the procedure
+@code{host} (which wraps around @code{%host}) is used instead.
+@end quotation
+@end defvar
+
@defvar setuid-program-service-type
Type for the ``setuid-program service''. This service collects lists of
executable file names, passed as gexps, and adds them to the set of
diff --git a/gnu/services/base.scm b/gnu/services/base.scm
index 9e799445d2..e9fdafd5d0 100644
--- a/gnu/services/base.scm
+++ b/gnu/services/base.scm
@@ -20,6 +20,7 @@
;;; Copyright © 2022 Guillaume Le Vaillant <glv@posteo.net>
;;; Copyright © 2022 Justin Veilleux <terramorpha@cock.li>
;;; Copyright © 2022 ( <paren@disroot.org>
+;;; Copyright © 2023 Bruno Victal <mirai@makinata.eu>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -103,6 +104,14 @@
console-font-service
virtual-terminal-service-type
+ host
+ %host
+ host?
+ host-address
+ host-canonical-name
+ host-aliases
+ hosts-service-type
+
static-networking
static-networking?
static-networking-addresses
@@ -685,6 +694,72 @@ to add @var{device} to the kernel's entropy pool. The service will fail if
(rngd-configuration
(rng-tools rng-tools)
(device device))))
+
+;;;
+;;; /etc/hosts
+;;;
+
+(define (valid-name? name)
+ "Return true if @var{name} is likely to be a valid host name."
+ (false-if-exception (not (string-any char-set:whitespace name))))
+
+(define-compile-time-procedure (assert-valid-name (name valid-name?))
+ "Ensure @var{name} is likely to be a valid host name."
+ ;; TODO: RFC compliant implementation.
+ (unless (valid-name? name)
+ (raise
+ (make-compound-condition
+ (formatted-message (G_ "host name '~a' contains invalid characters")
+ name)
+ (condition (&error-location
+ (location
+ (source-properties->location procedure-call-location)))))))
+ name)
+
+(define-record-type* <host> %host
+ ;; XXX: Using the record type constructor becomes tiresome when
+ ;; there's multiple records to make.
+ make-host host?
+ (address host-address)
+ (canonical-name host-canonical-name
+ (sanitize assert-valid-name))
+ (aliases host-aliases
+ (default '())
+ (sanitize (cut map assert-valid-name <>))))
+
+(define* (host address canonical-name #:optional (aliases '()))
+ "Return a new record for the host at @var{address} with the given
+@var{canonical-name} and possibly @var{aliases}.
+
+@var{address} must be a string denoting a valid IPv4 or IPv6 address, and
+@var{canonical-name} and the strings listed in @var{aliases} must be valid
+host names."
+ (%host
+ (address address)
+ (canonical-name canonical-name)
+ (aliases aliases)))
+
+(define hosts-service-type
+ ;; Extend etc-service-type with a entry for @file{/etc/hosts}.
+ (let* ((serialize-host-record
+ (lambda (record)
+ (match-record record <host> (address canonical-name aliases)
+ (format #f "~a~/~a~{~^~/~a~}~%" address canonical-name aliases))))
+ (host-etc-service
+ (lambda (lst)
+ `(("hosts" ,(plain-file "hosts"
+ (format #f "~{~a~}"
+ (map serialize-host-record
+ lst))))))))
+ (service-type
+ (name 'etc-hosts)
+ (extensions
+ (list
+ (service-extension etc-service-type
+ host-etc-service)))
+ (compose concatenate)
+ (extend append)
+ (description "Populate the @file{/etc/hosts} file."))))
;;;