Table of Contents

GNU Guix System

GNU Guix System is a distribution based on Guix package manager. It allows one to declaratively configure the system and its services, a concept shared with NixOS. While NixOS uses the Nix language, Guix is built with Guile Scheme. This page describes Guix specifics on vpsFree.cz's VPS.

Configuration

The VPS is created from a template which contains a minimal system with SSH. You can log in with a generated password or deploy your public key using vpsAdmin. The system can then be configured using guix system reconfigure.

System configuration is stored in directory /etc/config:

# . /etc/profile
# guix pull
# hash guix
# guix system reconfigure /etc/config/system.scm

Networking is handled by /ifcfg.add script, which is generated by vpsadminos on every VPS restart. The script is executed using vpsadminos-networking shepherd service. Due to how dynamic the environment is (IPv6 route changes on every reboot), using static-networking-service-type is simply not possible.

Known issues

Alternative configuration for guix deploy

Slightly adjusted, single file, alternative configuration can be found below to be used as a starting point for your guix deploy setup. It pretty much is just an amalgamation of the default setup into one file, with few tweaks here and there. Differences are:

(use-modules (gnu)
             (gnu machine)
             (gnu machine ssh)
             (gnu packages bash)
             (gnu packages certs)
             (gnu packages ssh)
             (gnu services networking)
             (gnu services shepherd)
             (gnu services ssh)
             (guix build-system trivial)
             (guix packages)
             (srfi srfi-1))
 
;;; The bootloader is not required.  This is running inside a container, and the
;;; start menu is populated by parsing /var/guix/profiles.  However bootloader
;;; is a mandatory field, and the typical grub-bootloader requires users to
;;; always pass the --no-bootloader flag.  By providing this bootloader
;;; configuration (it does not do anything, but installs fine), we remove the
;;; need to remember to pass the flag.  At the cost of ~8MB in /boot.
(define %ct-bootloader
  (bootloader-configuration
   ;; This one can be installed without efivars and without block device.
   (bootloader grub-efi-netboot-removable-bootloader)
   (targets '("/boot"))))
 
;;; It seems any package can be passed as an kernel, so create empty one for
;;; that purpose.
(define %ct-dummy-kernel
  (package
    (name "dummy-kernel")
    (version "1")
    (source #f)
    (build-system trivial-build-system)
    (arguments
     (list
      #:builder #~(mkdir #$output)))
    (synopsis "Dummy kernel")
    (description
     "In container environment, the kernel is provided by the host.  However we
still need to specify a kernel in the operating-system definition, hence this
package.")
    (home-page #f)
    (license #f)))
 
(define %ct-file-systems
  (cons* (file-system                   ; Dummy rootfs
           (device "/dev/null")
           (mount-point "/")
           (type "dummy"))
         ;; Used by vpsadminos scripting.  Can go away once /run as a whole is
         ;; on tmpfs.
         (file-system
           (device "none")
           (mount-point "/run/vpsadminos")
           (type "tmpfs")
           (check? #f)
           (flags '(no-suid no-dev no-exec))
           (options "mode=0755")
           (create-mount-point? #t))
         (map (λ (fs)
                (cond
                 ;; %immutable-store is usually mounted with no-atime.  That
                 ;; does not work in the vpsFree (causing the boot to hang), so
                 ;; we need to delete the flag.
                 ((eq? fs %immutable-store)
                  (file-system
                    (inherit fs)
                    (flags (delete 'no-atime (file-system-flags fs)))))
                 (else
                  fs)))
              (fold delete
                    %base-file-systems
                    (list
                     ;; Already mounted by vpsadminos
                     %pseudo-terminal-file-system
                     ;; Cannot be mounted due to the permissions
                     %debug-file-system
                     %efivars-file-system)))))
 
(define vpsadminos-networking
  (shepherd-service
   (requirement '(file-system-/run/vpsadminos))
   (provision '(vpsadminos-networking networking loopback))
   (documentation "Setup network on vpsAdminOS")
   (one-shot? #t)
   (start #~(lambda _ (invoke #$(file-append bash "/bin/bash")
                              "-c" "
[ -f  /run/vpsadminos/network ] && exit 0
touch /run/vpsadminos/network
\"$SHELL\" /ifcfg.add
")))))
 
(define %ct-services
  (cons* (service mingetty-service-type
                  (mingetty-configuration
                   (tty "console")))
         (simple-service 'vpsadminos-networking
                         shepherd-root-service-type (list vpsadminos-networking))
 
         (modify-services %base-services
           (delete console-font-service-type)
           (delete agetty-service-type)
           (delete mingetty-service-type)
           (delete urandom-seed-service-type)
           ;; loopback is configured by vpsadminos-networking
           (delete static-networking-service-type)
           ;; We need no rules.
           (udev-service-type config =>
                              (udev-configuration
                               (inherit config)
                               (rules '()))))))
 
(define %signing-key
  ;; Fill this with your local signing key (/etc/guix/signing-key.pub).
  "...")
 
(define %system
  (operating-system
    (host-name "guix")
    ;; Servers usually use UTC regardless of the location.
    (timezone "Etc/UTC")
    (locale "en_US.utf8")
 
    (kernel %ct-dummy-kernel)
    (bootloader %ct-bootloader)
 
    (firmware '())
    (initrd-modules '())
 
    (packages (cons* nss-certs
                     %base-packages))
 
    (essential-services
     (modify-services
         (operating-system-default-essential-services this-operating-system)
       (delete firmware-service-type)
       (delete (service-kind %linux-bare-metal-service))))
 
    (file-systems %ct-file-systems)
 
    (services
     (cons* (service openssh-service-type
                     (openssh-configuration
                      (openssh openssh-sans-x)
                      (permit-root-login #t)
                      ;; Only keys are allowed.
                      (password-authentication? #f)))
            (simple-service 'extra-authorized-keys guix-service-type
                            (guix-extension
                             (authorized-keys
                              (list (plain-file "signing-key" %signing-key)))))
            %ct-services))))
 
;;; Set this to the SSH key of the machine.
(define %host-key
  "ssh-ed25519 ...")
 
(define %machine
  (machine
   (operating-system %system)
   (environment managed-host-environment-type)
   (configuration (machine-ssh-configuration
                   ;; Put the IP or host name here.
                   (host-name "...")
                   (system "x86_64-linux")
                   (host-key %host-key)
                   (allow-downgrades? #t)
                   (safety-checks? #f)))))
 
(list %machine)

If you will go via the guix deploy route, you should likely delete the /etc/config directory to prevent any confusion.