336 lines
14 KiB
Scheme
336 lines
14 KiB
Scheme
(define-module (fruix system freebsd model)
|
|
#:use-module (fruix packages freebsd)
|
|
#:use-module (ice-9 match)
|
|
#:use-module (srfi srfi-1)
|
|
#:use-module (srfi srfi-9)
|
|
#:use-module (srfi srfi-13)
|
|
#:export (user-group
|
|
user-group?
|
|
user-group-name
|
|
user-group-gid
|
|
user-group-system?
|
|
user-account
|
|
user-account?
|
|
user-account-name
|
|
user-account-uid
|
|
user-account-group
|
|
user-account-supplementary-groups
|
|
user-account-comment
|
|
user-account-home
|
|
user-account-shell
|
|
user-account-system?
|
|
file-system
|
|
file-system?
|
|
file-system-device
|
|
file-system-mount-point
|
|
file-system-type
|
|
file-system-options
|
|
file-system-needed-for-boot?
|
|
operating-system
|
|
operating-system?
|
|
operating-system-host-name
|
|
operating-system-freebsd-base
|
|
operating-system-kernel
|
|
operating-system-bootloader
|
|
operating-system-base-packages
|
|
operating-system-users
|
|
operating-system-groups
|
|
operating-system-file-systems
|
|
operating-system-services
|
|
operating-system-loader-entries
|
|
operating-system-rc-conf-entries
|
|
operating-system-init-mode
|
|
operating-system-ready-marker
|
|
operating-system-root-authorized-keys
|
|
default-minimal-operating-system
|
|
freebsd-source-spec
|
|
freebsd-base-spec
|
|
validate-freebsd-source
|
|
validate-operating-system
|
|
pid1-init-mode?
|
|
effective-loader-entries
|
|
rc-conf-entry-value
|
|
sshd-enabled?
|
|
operating-system-generated-file-names
|
|
operating-system-closure-spec))
|
|
|
|
(define-record-type <user-group>
|
|
(make-user-group name gid system?)
|
|
user-group?
|
|
(name user-group-name)
|
|
(gid user-group-gid)
|
|
(system? user-group-system?))
|
|
|
|
(define* (user-group #:key name gid (system? #t))
|
|
(make-user-group name gid system?))
|
|
|
|
(define-record-type <user-account>
|
|
(make-user-account name uid group supplementary-groups comment home shell system?)
|
|
user-account?
|
|
(name user-account-name)
|
|
(uid user-account-uid)
|
|
(group user-account-group)
|
|
(supplementary-groups user-account-supplementary-groups)
|
|
(comment user-account-comment)
|
|
(home user-account-home)
|
|
(shell user-account-shell)
|
|
(system? user-account-system?))
|
|
|
|
(define* (user-account #:key name uid group (supplementary-groups '())
|
|
(comment "Fruix user") (home "/nonexistent")
|
|
(shell "/usr/sbin/nologin") (system? #t))
|
|
(make-user-account name uid group supplementary-groups comment home shell system?))
|
|
|
|
(define-record-type <file-system>
|
|
(make-file-system device mount-point type options needed-for-boot?)
|
|
file-system?
|
|
(device file-system-device)
|
|
(mount-point file-system-mount-point)
|
|
(type file-system-type)
|
|
(options file-system-options)
|
|
(needed-for-boot? file-system-needed-for-boot?))
|
|
|
|
(define* (file-system #:key device mount-point type (options "rw")
|
|
(needed-for-boot? #f))
|
|
(make-file-system device mount-point type options needed-for-boot?))
|
|
|
|
(define-record-type <operating-system>
|
|
(make-operating-system host-name freebsd-base kernel bootloader base-packages users groups
|
|
file-systems services loader-entries rc-conf-entries
|
|
init-mode ready-marker root-authorized-keys)
|
|
operating-system?
|
|
(host-name operating-system-host-name)
|
|
(freebsd-base operating-system-freebsd-base)
|
|
(kernel operating-system-kernel)
|
|
(bootloader operating-system-bootloader)
|
|
(base-packages operating-system-base-packages)
|
|
(users operating-system-users)
|
|
(groups operating-system-groups)
|
|
(file-systems operating-system-file-systems)
|
|
(services operating-system-services)
|
|
(loader-entries operating-system-loader-entries)
|
|
(rc-conf-entries operating-system-rc-conf-entries)
|
|
(init-mode operating-system-init-mode)
|
|
(ready-marker operating-system-ready-marker)
|
|
(root-authorized-keys operating-system-root-authorized-keys))
|
|
|
|
(define* (operating-system #:key
|
|
(host-name "fruix-freebsd")
|
|
(freebsd-base %default-freebsd-base)
|
|
(kernel freebsd-kernel)
|
|
(bootloader freebsd-bootloader)
|
|
(base-packages %freebsd-system-packages)
|
|
(users (list (user-account #:name "root"
|
|
#:uid 0
|
|
#:group "wheel"
|
|
#:comment "Charlie &"
|
|
#:home "/root"
|
|
#:shell "/bin/sh"
|
|
#:system? #t)
|
|
(user-account #:name "operator"
|
|
#:uid 1000
|
|
#:group "operator"
|
|
#:supplementary-groups '("wheel")
|
|
#:comment "Fruix Operator"
|
|
#:home "/home/operator"
|
|
#:shell "/bin/sh"
|
|
#:system? #f)))
|
|
(groups (list (user-group #:name "wheel" #:gid 0 #:system? #t)
|
|
(user-group #:name "operator" #:gid 1000 #:system? #f)))
|
|
(file-systems (list (file-system #:device "/dev/ufs/fruix-root"
|
|
#:mount-point "/"
|
|
#:type "ufs"
|
|
#:options "rw"
|
|
#:needed-for-boot? #t)
|
|
(file-system #:device "devfs"
|
|
#:mount-point "/dev"
|
|
#:type "devfs"
|
|
#:options "rw"
|
|
#:needed-for-boot? #t)
|
|
(file-system #:device "tmpfs"
|
|
#:mount-point "/tmp"
|
|
#:type "tmpfs"
|
|
#:options "rw,size=64m"
|
|
#:needed-for-boot? #f)))
|
|
(services '(shepherd ready-marker))
|
|
(loader-entries '(("autoboot_delay" . "1")
|
|
("console" . "comconsole")))
|
|
(rc-conf-entries '(("clear_tmp_enable" . "YES")
|
|
("sendmail_enable" . "NONE")
|
|
("sshd_enable" . "NO")))
|
|
(init-mode 'freebsd-init+rc.d-shepherd)
|
|
(ready-marker "/var/lib/fruix/ready")
|
|
(root-authorized-keys '()))
|
|
(make-operating-system host-name freebsd-base kernel bootloader base-packages users groups
|
|
file-systems services loader-entries rc-conf-entries
|
|
init-mode ready-marker root-authorized-keys))
|
|
|
|
(define default-minimal-operating-system (operating-system))
|
|
|
|
(define (package-names packages)
|
|
(map freebsd-package-name packages))
|
|
|
|
(define (freebsd-source-spec source)
|
|
`((name . ,(freebsd-source-name source))
|
|
(kind . ,(freebsd-source-kind source))
|
|
(url . ,(freebsd-source-url source))
|
|
(path . ,(freebsd-source-path source))
|
|
(ref . ,(freebsd-source-ref source))
|
|
(commit . ,(freebsd-source-commit source))
|
|
(sha256 . ,(freebsd-source-sha256 source))))
|
|
|
|
(define (freebsd-base-spec base)
|
|
`((name . ,(freebsd-base-name base))
|
|
(version-label . ,(freebsd-base-version-label base))
|
|
(release . ,(freebsd-base-release base))
|
|
(branch . ,(freebsd-base-branch base))
|
|
(source-root . ,(freebsd-base-source-root base))
|
|
(source . ,(freebsd-source-spec (freebsd-base-source base)))
|
|
(target . ,(freebsd-base-target base))
|
|
(target-arch . ,(freebsd-base-target-arch base))
|
|
(kernconf . ,(freebsd-base-kernconf base))
|
|
(make-flags . ,(freebsd-base-make-flags base))))
|
|
|
|
|
|
(define (duplicate-elements values)
|
|
(let loop ((rest values) (seen '()) (duplicates '()))
|
|
(match rest
|
|
(() (reverse duplicates))
|
|
((head . tail)
|
|
(if (member head seen)
|
|
(loop tail seen (if (member head duplicates) duplicates (cons head duplicates)))
|
|
(loop tail (cons head seen) duplicates))))))
|
|
|
|
(define (non-empty-string? value)
|
|
(and (string? value)
|
|
(not (string-null? value))))
|
|
|
|
(define (validate-freebsd-source source)
|
|
(unless (freebsd-source? source)
|
|
(error "freebsd base source must be a <freebsd-source> record"))
|
|
(let ((kind (freebsd-source-kind source)))
|
|
(unless (member kind '(local-tree git src-txz))
|
|
(error "unsupported freebsd source kind" kind))
|
|
(case kind
|
|
((local-tree)
|
|
(unless (non-empty-string? (freebsd-source-path source))
|
|
(error "local-tree freebsd source must declare a path" source)))
|
|
((git)
|
|
(unless (non-empty-string? (freebsd-source-url source))
|
|
(error "git freebsd source must declare a URL" source))
|
|
(unless (or (non-empty-string? (freebsd-source-ref source))
|
|
(non-empty-string? (freebsd-source-commit source)))
|
|
(error "git freebsd source must declare a ref or commit" source)))
|
|
((src-txz)
|
|
(unless (non-empty-string? (freebsd-source-url source))
|
|
(error "src-txz freebsd source must declare a URL" source))
|
|
(unless (non-empty-string? (freebsd-source-sha256 source))
|
|
(error "src-txz freebsd source must declare a sha256" source)))))
|
|
#t)
|
|
|
|
(define (validate-operating-system os)
|
|
(let* ((host-name (operating-system-host-name os))
|
|
(base (operating-system-freebsd-base os))
|
|
(users (operating-system-users os))
|
|
(groups (operating-system-groups os))
|
|
(file-systems (operating-system-file-systems os))
|
|
(user-names (map user-account-name users))
|
|
(group-names (map user-group-name groups))
|
|
(mount-points (map file-system-mount-point file-systems))
|
|
(init-mode (operating-system-init-mode os)))
|
|
(when (string-null? host-name)
|
|
(error "operating-system host-name must not be empty"))
|
|
(unless (freebsd-base? base)
|
|
(error "operating-system freebsd-base must be a <freebsd-base> record"))
|
|
(validate-freebsd-source (freebsd-base-source base))
|
|
(let ((dups (duplicate-elements user-names)))
|
|
(unless (null? dups)
|
|
(error "duplicate user names in operating-system" dups)))
|
|
(let ((dups (duplicate-elements group-names)))
|
|
(unless (null? dups)
|
|
(error "duplicate group names in operating-system" dups)))
|
|
(unless (member "/" mount-points)
|
|
(error "operating-system must declare a root file-system"))
|
|
(unless (member "root" user-names)
|
|
(error "operating-system must declare a root user"))
|
|
(unless (member "wheel" group-names)
|
|
(error "operating-system must declare a wheel group"))
|
|
(unless (member init-mode '(freebsd-init+rc.d-shepherd shepherd-pid1))
|
|
(error "unsupported operating-system init-mode" init-mode))
|
|
#t))
|
|
|
|
(define (pid1-init-mode? os)
|
|
(eq? (operating-system-init-mode os) 'shepherd-pid1))
|
|
|
|
(define (effective-loader-entries os)
|
|
(append (if (pid1-init-mode? os)
|
|
'(("init_exec" . "/run/current-system/boot/fruix-pid1"))
|
|
'())
|
|
(operating-system-loader-entries os)))
|
|
|
|
(define (rc-conf-entry-value os key)
|
|
(let ((entry (assoc key (operating-system-rc-conf-entries os))))
|
|
(and entry (cdr entry))))
|
|
|
|
(define (sshd-enabled? os)
|
|
(let ((value (rc-conf-entry-value os "sshd_enable")))
|
|
(and value
|
|
(member (string-upcase value) '("YES" "TRUE" "1")))))
|
|
|
|
|
|
(define (operating-system-generated-file-names os)
|
|
(append
|
|
'("boot/loader.conf"
|
|
"etc/rc.conf"
|
|
"etc/fstab"
|
|
"etc/hosts"
|
|
"etc/passwd"
|
|
"etc/master.passwd"
|
|
"etc/group"
|
|
"etc/login.conf"
|
|
"etc/shells"
|
|
"etc/motd"
|
|
"etc/ttys"
|
|
"metadata/freebsd-base.scm"
|
|
"metadata/host-base-provenance.scm"
|
|
"metadata/store-layout.scm"
|
|
"activate"
|
|
"shepherd/init.scm"
|
|
"usr/local/bin/fruix")
|
|
(if (pid1-init-mode? os)
|
|
'("boot/fruix-pid1")
|
|
'())
|
|
(if (sshd-enabled? os)
|
|
'("etc/ssh/sshd_config")
|
|
'())
|
|
(if (null? (operating-system-root-authorized-keys os))
|
|
'()
|
|
'("root/.ssh/authorized_keys"))))
|
|
|
|
|
|
(define (operating-system-closure-spec os)
|
|
(validate-operating-system os)
|
|
`((host-name . ,(operating-system-host-name os))
|
|
(freebsd-base . ,(freebsd-base-spec (operating-system-freebsd-base os)))
|
|
(kernel-package . ,(freebsd-package-name (operating-system-kernel os)))
|
|
(bootloader-package . ,(freebsd-package-name (operating-system-bootloader os)))
|
|
(base-package-count . ,(length (operating-system-base-packages os)))
|
|
(base-packages . ,(package-names (operating-system-base-packages os)))
|
|
(user-count . ,(length (operating-system-users os)))
|
|
(users . ,(map user-account-name (operating-system-users os)))
|
|
(group-count . ,(length (operating-system-groups os)))
|
|
(groups . ,(map user-group-name (operating-system-groups os)))
|
|
(file-system-count . ,(length (operating-system-file-systems os)))
|
|
(file-systems . ,(map (lambda (fs)
|
|
`((device . ,(file-system-device fs))
|
|
(mount-point . ,(file-system-mount-point fs))
|
|
(type . ,(file-system-type fs))
|
|
(options . ,(file-system-options fs))
|
|
(needed-for-boot? . ,(file-system-needed-for-boot? fs))))
|
|
(operating-system-file-systems os)))
|
|
(services . ,(operating-system-services os))
|
|
(generated-files . ,(operating-system-generated-file-names os))
|
|
(init-mode . ,(operating-system-init-mode os))
|
|
(ready-marker . ,(operating-system-ready-marker os))))
|
|
|