359 lines
13 KiB
Org Mode
359 lines
13 KiB
Org Mode
#+TITLE: Guix Machines
|
|
#+AUTHOR: Collin J. Doering
|
|
|
|
#+BEGIN_EXPORT html
|
|
<p><a href="https://guix-ci.home.rekahsoft.ca/jobset/guix-machines"><img src="https://guix-ci.home.rekahsoft.ca/jobset/guix-machines/badge.svg?type=0" alt="Cuirass Status"></a></p>
|
|
#+END_EXPORT
|
|
|
|
#+begin_abstract
|
|
Guix configurations for all Guix powered servers privately managed by the author. This
|
|
includes all virtual machines for my home network and cloud/vps instances. Two mutable
|
|
deployment methodologies are supported:
|
|
|
|
1. A push based model, using ~guix deploy~[fn:1] to remotely deploy changes (useful for example
|
|
from ci/cd).
|
|
2. A pull based model, using ~guix~ directly from the target, along with either the entire
|
|
repository, or its channel file.
|
|
|
|
Immutable deployment is not yet supported, but is certainly possible given Guix's ability to
|
|
build an ~operating-system~ configuration into a image.
|
|
#+end_abstract
|
|
|
|
* Repository Structure
|
|
|
|
- ~channels*.scm~ :: [[*Guix Channel Files][Guix channel files]]
|
|
- ~deploy/~ :: Folder containing all ~guix deploy~ configurations
|
|
- ~.gitignore~ :: Files ignored by git
|
|
- ~.guix/~ :: Guix channel directory
|
|
- ~.guix-authorizations~ :: Guix authorizations file[fn:2]
|
|
- ~.guix-channel~ :: Guix channel file[fn:3]
|
|
- ~.pub-keys/~ :: Folder containing public key files used by Guix configurations
|
|
- ~README.org~ :: Org-mode[fn:4] documentation
|
|
- ~TODO.org~ :: Org-mode todo's, known issues and future aspirations
|
|
- ~unguix/~ :: Docker/docker-compose files used on deployed instances, managed
|
|
outside of guix. Once better support for running docker/docker-compose via shepherd,
|
|
specified declaratively via Guix configuration has been implemented, this directory and all
|
|
files within it should be able to be removed.
|
|
|
|
** User Supplied Files Required for Push Based Deployment
|
|
|
|
- ~.deploy-key~ :: Private ssh key used to deploy changes to the target.
|
|
|
|
** Guix Channel Files
|
|
|
|
Guix channels[fn:5] allow for Guix to be customized and extended. They are also critical for
|
|
replicating a Guix system[fn:6]. As mentioned above, there are two primary classes of
|
|
deployments that are managed using this repository, push based and pull based. In both cases,
|
|
what specific versions of software that will be installed during deployment depends on the
|
|
guix channels in use. To ensure reproducibility, a ~channels.scm~ file is provided in this
|
|
repository that is expected to be used during deployment. It pins external guix channels to
|
|
specific versions.
|
|
|
|
If for some reason channels need to be pinned for a specific deployment, a new channel file
|
|
named ~channels-<hostname>.scm~ can be created and used in place of normally used channel
|
|
file.
|
|
|
|
*** TODO Updating guix channels used for deployment
|
|
|
|
**This doesn't work right unless your channels match what is expected by this repository.**
|
|
|
|
#+begin_src shell
|
|
guix time-machine -- describe -f channels > channels.scm
|
|
#+end_src
|
|
|
|
** ~guix-machines~ the Guix Channel
|
|
|
|
This repository is itself a Guix channel, which allows operating-system configurations to
|
|
come directly from the channel, and the version of this configuration be managed just like
|
|
any other guix channel. It also facilitates CI, allowing for changes this channel be
|
|
evaluated by Cuirass at [[https://guix-ci.home.rekahsoft.ca]][fn:7]. This channel does not define
|
|
any packages, only system configurations and machine specifications for deployment.
|
|
|
|
At a later date, this also will allow for building of machine images for immutable
|
|
deployment, bootstrapping and more.
|
|
|
|
* TODO Initializing a System
|
|
|
|
** Using an existing guix installation image
|
|
|
|
*** TODO Producing an installation image
|
|
|
|
TODO: It would be convent to be able to produce an image that can be used to install my
|
|
normal setup. This would avoid pulling my channels, as well as downloading software (it could
|
|
all be pre-packaged in the image).
|
|
|
|
If you produce and use this installation image, you can skip to [[*Disk Setup and Partitioning][Disk Setup and Partitioning]].
|
|
|
|
*** TODO Setup Installation
|
|
|
|
TODO: network needs to be setup; local, keymap, and font too.
|
|
|
|
*** Configure Guix Channels
|
|
|
|
First, fetch the most recent channel file from the target machine. For most, this will be
|
|
done via the internet using my public mirror.
|
|
|
|
#+begin_src shell
|
|
curl -O https://git.rekahsoft.ca/rekahsoft/guix-machines/raw/branch/master/channels.scm
|
|
#+end_src
|
|
|
|
When on my network, I pull from my internal git (notice the different URL).
|
|
|
|
#+begin_src shell
|
|
curl -O https://git.home.rekahsoft.ca/rekahsoft-public/guix-machines/raw/branch/master/channels.scm
|
|
#+end_src
|
|
|
|
Once the channel file is available on the target, refresh the cached command paths with
|
|
~hash~ and update guix to use the new channels.
|
|
|
|
#+begin_src shell
|
|
hash guix
|
|
sudo -i guix pull -C $(realpath channels.scm)
|
|
#+end_src
|
|
|
|
*** TODO Disk Setup and Partitioning
|
|
|
|
TODO: disks need to be partitioned and appropriately mounted. This varies depending on the setup.
|
|
|
|
#+begin_src bash
|
|
# Create disk partition table and layout
|
|
parted /dev/nvme0n1 mklabel gpt
|
|
|
|
# Create partitions
|
|
parted /dev/nvme0n1 mkpart primary ESP 0% 512MiB
|
|
parted /dev/nvme0n1 mkpart 512MiB 100%
|
|
|
|
# Create EFI partition
|
|
parted /dev/nvme0n1p1 set 1 esp on
|
|
mkfs.fat -F32 /dev/nvme0n1p1
|
|
|
|
# Create LUKS container on remainder of disk
|
|
cryptsetup luksFormat --label crypt /dev/nvme0n1p2
|
|
|
|
# Unlock LUKS container after creation
|
|
cryptsetup luksOpen /dev/nvme0n1p2 crypt
|
|
|
|
#
|
|
# Create LVM2 container inside of LUKS container
|
|
|
|
# Create Physical Volume (pv)
|
|
pvcreate /dev/mapper/crypt
|
|
|
|
# Create Volume Group (vg)
|
|
vgcreate vg0 /dev/mapper/crypt
|
|
|
|
# Create Logical Volume/s (vg)
|
|
lvcreate -L <ROOT_VOL_SIZE>G vg0 -n root
|
|
lvcreate -l +100%FREE vg0 -n swap
|
|
|
|
#
|
|
# Create btrfs 'pool' (file-system) and subvolumes
|
|
|
|
# Create btrfs file-system
|
|
mkfs.btrfs --label root /dev/vg0/root
|
|
|
|
# Create btrfs subvolumes
|
|
mount /dev/vg0/root /mnt
|
|
btrfs subvolume create /mnt/@
|
|
umount /mnt
|
|
|
|
# Mount the root subvolume.
|
|
mount -o subvol=@,compress=zstd /dev/vg0/root /mnt
|
|
|
|
# Create nested subvolumes for /gnu/store, /home, and /var
|
|
mkdir -p /mnt/gnu
|
|
btrfs subvolume create /mnt/gnu/store
|
|
btrfs subvolume create /mnt/home
|
|
btrfs subvolume create /mnt/var
|
|
|
|
# Create and activate swap
|
|
mkswap --label swap /dev/vg0/swap
|
|
swapon /dev/vg0/swap
|
|
|
|
# Prepare /mnt for Guix installation
|
|
mkdir -p /mnt/boot/efi
|
|
mount /dev/nvme0n1p1 /mnt/boot/efi
|
|
#+end_src
|
|
|
|
*** Bootstrap System
|
|
|
|
**** Start ~cow-store~ Service
|
|
|
|
As described in guix documentation, start ~cow-store~ to allow later steps to write store
|
|
changes to ~/mnt/gnu/store~.
|
|
|
|
#+begin_src bash
|
|
herd start cow-store /mnt
|
|
#+end_src
|
|
|
|
**** Optional (but recommended): Use additional or alternative substitute servers
|
|
|
|
Optionally additional or alternative substitute servers can be setup for guix-daemon. This is
|
|
recommended to greatly speed up installation (so that nonguix and rekahsoft-guix (internal
|
|
network only) substitutes can be used).
|
|
|
|
First stop the running ~guix-daemon~.
|
|
|
|
#+begin_src bash
|
|
herd stop guix-daemon
|
|
#+end_src
|
|
|
|
Then start a new instance of ~guix-daemon~ as it is normally started by its Shepherd service,
|
|
but with additional or alternative substitute servers provided.
|
|
|
|
#+begin_src bash
|
|
guix-daemon \
|
|
--build-users-group guixbuild \
|
|
--max-silent-time 0 \
|
|
--timeout 0 \
|
|
--log-compression gzip \
|
|
--discover=no \
|
|
--substitute-urls https://substitutes.nonguix.org https://guix-ci.home.rekahsoft.ca https://ci.guix.gnu.org https://bordeaux.guix.gnu.org &
|
|
#+end_src
|
|
|
|
**** Create and Bootstrap System
|
|
|
|
Create a ~bootstrap.scm~ file like this:
|
|
|
|
#+begin_src scheme
|
|
(@ (rekahsoft guix-config vms <target>) %system)
|
|
#+end_src
|
|
|
|
Use ~guix system init ...~ to instantiate the system.
|
|
|
|
#+begin_src bash
|
|
guix system init bootstrap.scm /mnt
|
|
#+end_src
|
|
|
|
** TODO Producing an image to be flashed directly
|
|
|
|
TODO: there are limitations on what images I can produce; namely, lvm and luks cannot be
|
|
setup easily (or at all?) it seems?
|
|
|
|
#+begin_src shell
|
|
guix time-machine -C channels.scm -- system image -e '(@ (rekahsoft guix-config vms <target>) %image)'
|
|
#+end_src
|
|
|
|
* Push Deployment with ~guix deploy~
|
|
|
|
Push based mutable deployment is the default deployment methodology for the majority of
|
|
systems managed by this repository. This is particularity safe because Guix changes are done
|
|
as transactions, and thus can easily be rolled back.
|
|
|
|
To deploy a system use the following (substituting ~<hostname>~ with the appropriate deploy
|
|
file).
|
|
|
|
#+begin_src shell
|
|
guix time-machine -C channels.scm -- deploy deploy/<hostname>.scm
|
|
#+end_src
|
|
|
|
**Note:** Deploy files in [[./deploy]] are named after the hostname that would be used to ssh to
|
|
the machine.
|
|
|
|
* Pull Based Deployment
|
|
|
|
Pull based mutable deployment is the default deployment methodology for personal computers,
|
|
where using a push based method doesn't make sense. It also serves as a secondary deployment
|
|
mechanism for systems normally maintained using the push deployment model; for example, this
|
|
becomes necessary when facing ~guix deploy~ bugs.
|
|
|
|
First [[*Configure Guix Channels][Configure Guix Channels]] as described above. Once channels have been updated
|
|
successfully, use the following to reconfigure the system.
|
|
|
|
#+begin_src shell
|
|
sudo -i guix system reconfigure -e '(@ (rekahsoft guix-config vms <target>) %system)'
|
|
#+end_src
|
|
|
|
Alternatively, the same effect can be achieved without first pulling the appropriate channels
|
|
by instead using ~guix time-machine~ as follows.
|
|
|
|
#+begin_src shell
|
|
sudo -i guix time-machine -C $(realpath channels.scm) -- system reconfigure -e '(@ (rekahsoft guix-config vms <target>) %system)'
|
|
#+end_src
|
|
|
|
* Using Local Sources
|
|
|
|
Regardless of the deployment methodology used, sometimes it is useful to deploy changes that
|
|
have not yet been committed. This should be done sparingly, as it can be slightly confusing
|
|
if forgotten; that being said, Guix makes this a semi-reasonable thing to do, as how the
|
|
system changes is tracked very explicitly by guix generations local to the target.
|
|
|
|
To manually deploy using local sources, the local sources must exist on the working machine
|
|
(of course). The easiest way to do this is via git, from the working machine like so. Most
|
|
will pull from my public git mirror.
|
|
|
|
#+begin_src shell
|
|
git clone https://git.rekahsoft.ca/rekahsoft/guix-machines.git
|
|
#+end_src
|
|
|
|
On my network, internal git is used instead (notice the different URL).
|
|
|
|
#+begin_src shell
|
|
git clone https://git.home.rekahsoft.ca/rekahsoft-public/guix-machines.git
|
|
#+end_src
|
|
|
|
Once a copy of the sources are available on the working machine, all that remains is
|
|
following the normal deployment steps, but with a slight modification; use the
|
|
~-L|--load-path~ argument to specify the current working sources, effectively overriding what
|
|
is in the ~guix-machines~ channel.
|
|
|
|
** Building Operating System Configuration
|
|
|
|
Many times its useful to verify that a change to a system configuration will build correctly,
|
|
prior to deploying it. ~guix system build~ is meant for exactly this, and can be run as
|
|
follows.
|
|
|
|
#+begin_src shell
|
|
guix time-machine -C channels.scm -- system build -L .guix -e '(@ (rekahsoft guix-config vms <target>) %system)'
|
|
#+end_src
|
|
|
|
** Running Operating System in VM for testing
|
|
|
|
#+begin_src shell
|
|
$(guix time-machine -C channels.scm -- system vm -e '(@ (rekahsoft guix-config vms <target>) %system)') -m 2G -smp 2 -nic user,model=virtio-net-pci
|
|
#+end_src
|
|
|
|
** Generating the OS service extension graph
|
|
|
|
#+begin_src shell
|
|
guix time-machine -C channels.scm -- system extension-graph -e '(@ (rekahsoft guix-config vms <target>) %system)' | guix shell xdot -- xdot -
|
|
#+end_src
|
|
|
|
** Generating the shepherd service graph
|
|
|
|
#+begin_src shell
|
|
guix time-machine -C channels.scm -- system shepherd-graph -e '(@ (rekahsoft guix-config vms <target>) %system)' | guix shell xdot -- xdot -
|
|
#+end_src
|
|
|
|
** Push Based Deployments
|
|
|
|
#+begin_src shell
|
|
guix time-machine -C channels.scm -- deploy -L ./.guix deploy/<hostname>.scm
|
|
#+end_src
|
|
|
|
See the [[*Push Deployment with ~guix deploy~][Push Deployment with ~guix deploy~]] section for more details.
|
|
|
|
** Pull Based Deployments
|
|
|
|
#+begin_src shell
|
|
sudo -i guix time-machine -C $(realpath channels.scm) -- system reconfigure -L $(realpath ./.guix) -e '(@ (rekahsoft guix-config vms <target>) %system)'
|
|
#+end_src
|
|
|
|
See the [[*Pull Based Deployment][Pull Based Deployment]] section for more details.
|
|
|
|
* Footnotes
|
|
|
|
[fn:1] https://guix.gnu.org/manual/en/html_node/Invoking-guix-deploy.html
|
|
|
|
[fn:2] https://guix.gnu.org/manual/en/html_node/Channel-Authentication.html
|
|
|
|
[fn:3] https://guix.gnu.org/manual/en/html_node/Package-Modules-in-a-Sub_002ddirectory.html
|
|
|
|
[fn:4] https://orgmode.org/
|
|
|
|
[fn:5] https://guix.gnu.org/manual/en/html_node/Channels.html
|
|
|
|
[fn:6] https://guix.gnu.org/manual/en/html_node/Replicating-Guix.html
|
|
|
|
[fn:7] Only available in my internal home-network
|