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's VPS.


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:

  • vpsadminos.scm contains configuration specific to our environment
  • system.scm loads vpsadminos.scm and is meant to be edited to configure the system
# . /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

  • halt (graceful shutdown) has been observed to sometimes hang, please report in case it's still a problem.
  • cgroups v1 are not mounted. cgroups do not seem to be needed by the base system, contact us in case it's a problem for some service or submit a patch to the template.
  • Hostname cannot be set using the vpsAdmin.
  • /gnu/store is not mounted with noatime flag. This could lead to reproducibility 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:

  • No dhcp-client-service-type, 'networking is handled directly by vpsadminos-networking service.
  • No password authentication is allowed for ssh.
  • In a single file.
  • Added parts for guix deploy
(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
   ;; 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
    (name "dummy-kernel")
    (version "1")
    (source #f)
    (build-system trivial-build-system)
      #:builder #~(mkdir #$output)))
    (synopsis "Dummy kernel")
     "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
    (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.
           (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)
                 ;; %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)
                    (inherit fs)
                    (flags (delete 'no-atime (file-system-flags fs)))))
              (fold delete
                     ;; Already mounted by vpsadminos
                     ;; Cannot be mounted due to the permissions
(define vpsadminos-networking
   (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
                   (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 =>
                               (inherit config)
                               (rules '()))))))
(define %signing-key
  ;; Fill this with your local signing key (/etc/guix/
(define %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
         (operating-system-default-essential-services this-operating-system)
       (delete firmware-service-type)
       (delete (service-kind %linux-bare-metal-service))))
    (file-systems %ct-file-systems)
     (cons* (service openssh-service-type
                      (openssh openssh-sans-x)
                      (permit-root-login #t)
                      ;; Only keys are allowed.
                      (password-authentication? #f)))
            (simple-service 'extra-authorized-keys guix-service-type
                              (list (plain-file "signing-key" %signing-key)))))
;;; Set this to the SSH key of the machine.
(define %host-key
  "ssh-ed25519 ...")
(define %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.

manuals/distributions/guix.txt · Last modified: 2023/12/20 12:18 by tomas.volf