diff --git a/.guix-channel b/.guix-channel
new file mode 100644
index 0000000000000000000000000000000000000000..292946e2518a0e69417ded45ee0da976a5ef3a54
--- /dev/null
+++ b/.guix-channel
@@ -0,0 +1,5 @@
+;; This file lets us present this repo as a Guix channel.
+
+(channel
+  (version 0)
+  (directory ".guix/modules"))  ;look for package modules under .guix/modules/
\ No newline at end of file
diff --git a/.guix/modules/ogs-package.scm b/.guix/modules/ogs-package.scm
new file mode 100644
index 0000000000000000000000000000000000000000..1562bc3e3d926ede42d0eb162d0ff70314d7fb5c
--- /dev/null
+++ b/.guix/modules/ogs-package.scm
@@ -0,0 +1,218 @@
+;; This file defines a Guix package.  It can be used to spawn an
+;; interactive development environment:
+;;
+;;   guix shell
+;;
+;; Or it can be used to build Guile from a checkout in an isolated
+;; environment:
+;;
+;;   guix build -f guix.scm
+;;
+;; Likewise, you may cross-compile it:
+;;
+;;   guix build -f guix.scm --target=x86_64-w64-mingw32
+;;
+;; Or may want to build a variant:
+;;   guix build -L $PWD/.guix/modules ogs-petsc-ssd
+
+(define-module (ogs-package)
+  #:use-module (guix)
+  #:use-module (guix packages)
+  #:use-module (guix build-system cmake)
+  #:use-module (guix download)
+  #:use-module (guix git-download)
+  #:use-module ((guix licenses) #:prefix license:)
+  #:use-module (gnu packages algebra)
+  #:use-module (gnu packages boost)
+  #:use-module (gnu packages check)
+  #:use-module (gnu packages certs) ; TODO: cpm
+  #:use-module (gnu packages cmake)
+  #:use-module (gnu packages compression)
+  #:use-module (gnu packages cpp)
+  #:use-module (gnu packages image-processing)
+  #:use-module (gnu packages logging)
+  #:use-module (gnu packages maths)
+  #:use-module (gnu packages mpi)
+  #:use-module (gnu packages ninja)
+  #:use-module (gnu packages pretty-print)
+  #:use-module (gnu packages python-xyz)
+  #:use-module (gnu packages python)
+  #:use-module (gnu packages version-control)
+  #:use-module (gnu packages xml)
+  )
+
+(define vcs-file?
+  ;; Return true if the given file is under version control.
+  (or (git-predicate "../..") ; (current-source-directory)
+      (const #t)))            ;not in a Git checkout
+
+(define-public ogs
+  (package
+    (name "ogs")
+    (version "6.4.99-git")
+    (source (local-file "../.." "ogs-checkout"
+                      #:recursive? #t
+                      #:select? vcs-file?
+                      ))
+    (build-system cmake-build-system)
+    (arguments
+     `(#:build-type "Release"
+       #:configure-flags (list
+        ; passing variables works like this
+        ;                  ,(string-append "-DOGS_VERSION=" version)
+        ; TODO: but it is not overwritten in sub-packages...
+                          "-DGUIX_BUILD=ON"
+                          "-DOGS_BUILD_TESTING=OFF"
+                          "-DOGS_USE_EIGEN_UNSUPPORTED=OFF" ; Eigen 3.4.0
+                          "-DOGS_INSTALL_DEPENDENCIES=OFF"  ; handled by guix
+                          "-DOGS_CPU_ARCHITECTURE=OFF"      ; enable guix --tune
+                          )
+       #:cmake ,cmake)) ;for newer CMake version
+    (inputs (list boost
+                  eigen
+                  fmt
+                  googletest
+                  hdf5
+                  json-modern-cxx
+                  libxml2
+                  pybind11-2.10.4
+                  python
+                  range-v3
+                  spdlog
+                  zlib
+                  vtk))
+    (native-inputs (list git ninja googletest nss-certs)) ; TODO: cpm
+    (synopsis "OpenGeoSys")
+    (description
+     "Simulation of thermo-hydro-mechanical-chemical (THMC) processes in porous and fractured media")
+    (home-page "https://www.opengeosys.org")
+    (properties '((tunable? . #t)))
+    (license license:bsd-3)))
+
+(define-public ogs-ssd
+  (package
+    (inherit ogs)
+    (name "ogs-ssd")
+    (arguments
+     (substitute-keyword-arguments (package-arguments ogs)
+       ((#:configure-flags flags)
+        `(cons* "-DOGS_BUILD_PROCESSES=SteadyStateDiffusion"
+                ,flags))))
+    (synopsis "OGS with SteadyStateDiffusion only (for faster build testing)")))
+
+(define-public ogs-petsc
+  (package
+    (inherit ogs)
+    (name "ogs-petsc")
+    (inputs (modify-inputs (package-inputs ogs)
+              (prepend openmpi petsc-openmpi)
+              (replace "vtk" vtk-openmpi)
+              (replace "hdf5" hdf5-parallel-openmpi)))
+    (arguments
+     (substitute-keyword-arguments (package-arguments ogs)
+       ((#:configure-flags flags)
+        `(cons* "-DOGS_USE_PETSC=ON"
+                "-DCMAKE_C_COMPILER=mpicc"
+                "-DCMAKE_CXX_COMPILER=mpic++"
+                ,flags))))
+    (synopsis "OGS with PETSc")))
+
+(define-public ogs-petsc-ssd
+  (package
+    (inherit ogs-petsc)
+    (name "ogs-petsc-ssd")
+    (arguments
+     (substitute-keyword-arguments (package-arguments ogs-petsc)
+       ((#:configure-flags flags)
+        `(cons* "-DOGS_BUILD_PROCESSES=SteadyStateDiffusion"
+                ,flags))))
+    (synopsis "OGS with PETSc and SteadyStateDiffusion only (for faster build testing)")))
+
+; #### Releases ####
+(define-public ogs-6.4.4
+  (package
+    (inherit ogs)
+    (name "ogs")
+    (version "6.4.4")
+    (source (origin
+              (method git-fetch)
+              (uri (git-reference
+                    (url "https://gitlab.opengeosys.org/ogs/ogs.git")
+                    (commit "d4ca7e627f2fc012bfe434649b797e78e5c2a8f1")
+                    (recursive? #t)))
+              (file-name (git-file-name name version))
+              (sha256
+               ;; Update with `guix hash -rx .`, make sure to have submodules updated!
+               (base32
+                "1f6mcbjx76irf1g0xkh6hgpv4qn2swbiyvlazvlrhjfyxb9bckq9"))))
+    (synopsis "OGS 6.4.4 release")))
+
+(define-public ogs-petsc-6.4.4
+  (package
+    (inherit ogs-petsc)
+    (name "ogs-petsc")
+    (version "6.4.4")
+    (source (origin
+              (method git-fetch)
+              (uri (git-reference
+                    (url "https://gitlab.opengeosys.org/ogs/ogs.git")
+                    (commit "d4ca7e627f2fc012bfe434649b797e78e5c2a8f1")
+                    (recursive? #t)))
+              (file-name (git-file-name name version))
+              (sha256
+               ;; Update with `guix hash -rx .`, make sure to have submodules updated!
+               (base32
+                "1f6mcbjx76irf1g0xkh6hgpv4qn2swbiyvlazvlrhjfyxb9bckq9"))))
+    (synopsis "OGS 6.4.4 with PETSc release")))
+
+; #### Dependencies ####
+(define-public vtk-openmpi
+  (package
+    (inherit vtk)
+    (name "vtk-openmpi")
+    (inputs (modify-inputs (package-inputs vtk)
+              (prepend hdf5-parallel-openmpi openmpi)))
+    (arguments
+     (substitute-keyword-arguments (package-arguments vtk)
+       ((#:configure-flags flags)
+        `(cons* "-DVTK_MODULE_ENABLE_VTK_IOParallelXML=YES"
+                "-DVTK_MODULE_ENABLE_VTK_ParallelMPI=YES" "-DVTK_USE_MPI=ON"
+                ,flags))))
+    (synopsis "VTK with OpenMPI support")))
+
+(define pybind11-2.10.4
+      (package
+        (inherit pybind11)
+        (version "2.10.4")
+        (source (origin
+                  (method git-fetch)
+                  (uri (git-reference
+                    (url "https://github.com/pybind/pybind11")
+                    (commit (string-append "v" version))))
+                  (sha256
+                   (base32
+                    "0rbcfvl7y472sykzdq3vrkw83kar0lpzhk3wq9yj9cdydl8cpfcz"))))))
+;; return package
+ogs
+
+;; TODO: add this to web page
+;  ## Using the ogs repo as a Guix channel (as a user of ogs)
+;
+;  Add the following to `~/.config/guix/channels.scm`:
+;
+;  ```scheme
+;  (append (list (channel
+;                  (name 'ogs)
+;                  (url "https://gitlab.opengeosys.org/ogs/ogs.git")
+;                  (branch "master"))) %default-channels)
+;  ```
+;
+;  Run `guix pull`.
+;
+;  Then you can install the ogs package:
+;
+;  ```bash
+;  guix install ogs@6.4.4
+;  # OR, e.g.
+;  guix install ogs-petsc@6.4.4
+;  ```
diff --git a/CMakePresets.json b/CMakePresets.json
index f40f3782a5dce862a5c915619550dd07b8c3e6a0..2bf82a1894e9cbc5818509ff77f6a69aba4b7546 100644
--- a/CMakePresets.json
+++ b/CMakePresets.json
@@ -9,7 +9,7 @@
     {
       "name": "_binary_dir",
       "hidden": true,
-      "binaryDir": "${sourceParentDir}/build/${presetName}"
+      "binaryDir": "${sourceParentDir}/build/$penv{CMAKE_PRESET_BUILD_DIR_PREFIX}${presetName}"
     },
     {
       "name": "_release",
diff --git a/ThirdParty/collection b/ThirdParty/collection
index d1ab058c383e29c95e25f9a0a63c687a3ef27a39..c47c2ed91cdfba1f46f62be2f25ccb8223ec125d 160000
--- a/ThirdParty/collection
+++ b/ThirdParty/collection
@@ -1 +1 @@
-Subproject commit d1ab058c383e29c95e25f9a0a63c687a3ef27a39
+Subproject commit c47c2ed91cdfba1f46f62be2f25ccb8223ec125d
diff --git a/guix.scm b/guix.scm
new file mode 120000
index 0000000000000000000000000000000000000000..80998e585e9d75acd0f70b7e084b9ab16673017d
--- /dev/null
+++ b/guix.scm
@@ -0,0 +1 @@
+.guix/modules/ogs-package.scm
\ No newline at end of file
diff --git a/scripts/ci/jobs/build-guix.yml b/scripts/ci/jobs/build-guix.yml
index 79372babd15de506a17f7f6c34caab5a789e71a7..2123db2a707f6f716fe6a39afb7875695154b3b9 100644
--- a/scripts/ci/jobs/build-guix.yml
+++ b/scripts/ci/jobs/build-guix.yml
@@ -10,4 +10,5 @@ build guix:
     - when: manual
       allow_failure: true
   script:
-    - guix time-machine --channels=scripts/guix/channels.scm -- build ogs-ssd ogs-petsc-ssd --with-source=ogs-ssd@6.4.4=$PWD --with-source=ogs-petsc-ssd@6.4.4=$PWD
+    - guix time-machine --commit=v1.4.0 -- build -L $PWD/.guix/modules ogs-ssd
+    - guix time-machine --commit=v1.4.0 -- build -L $PWD/.guix/modules ogs-petsc-ssd
diff --git a/scripts/cmake/CPM.cmake b/scripts/cmake/CPM.cmake
index c01a5b221a987834eb01d64815e0a2dbe351e75d..2e3767633ebcf2f34e60dda871686f97c51923d8 100644
--- a/scripts/cmake/CPM.cmake
+++ b/scripts/cmake/CPM.cmake
@@ -42,7 +42,7 @@ if(NOT COMMAND cpm_message)
   endfunction()
 endif()
 
-set(CURRENT_CPM_VERSION 0.37.0)
+set(CURRENT_CPM_VERSION 0.38.2)
 
 get_filename_component(CPM_CURRENT_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}" REALPATH)
 if(CPM_DIRECTORY)
@@ -513,8 +513,8 @@ function(CPMAddPackage)
   if(argnLength EQUAL 1)
     cpm_parse_add_package_single_arg("${ARGN}" ARGN)
 
-    # The shorthand syntax implies EXCLUDE_FROM_ALL
-    set(ARGN "${ARGN};EXCLUDE_FROM_ALL;YES")
+    # The shorthand syntax implies EXCLUDE_FROM_ALL and SYSTEM
+    set(ARGN "${ARGN};EXCLUDE_FROM_ALL;YES;SYSTEM;YES;")
   endif()
 
   set(oneValueArgs
@@ -531,6 +531,7 @@ function(CPMAddPackage)
       DOWNLOAD_COMMAND
       FIND_PACKAGE_ARGUMENTS
       NO_CACHE
+      SYSTEM
       GIT_SHALLOW
       EXCLUDE_FROM_ALL
       SOURCE_SUBDIR
@@ -626,6 +627,7 @@ function(CPMAddPackage)
       NAME "${CPM_ARGS_NAME}"
       SOURCE_DIR "${PACKAGE_SOURCE}"
       EXCLUDE_FROM_ALL "${CPM_ARGS_EXCLUDE_FROM_ALL}"
+      SYSTEM "${CPM_ARGS_SYSTEM}"
       OPTIONS "${CPM_ARGS_OPTIONS}"
       SOURCE_SUBDIR "${CPM_ARGS_SOURCE_SUBDIR}"
       DOWNLOAD_ONLY "${DOWNLOAD_ONLY}"
@@ -646,19 +648,21 @@ function(CPMAddPackage)
     return()
   endif()
 
-  if(CPM_USE_LOCAL_PACKAGES OR CPM_LOCAL_PACKAGES_ONLY)
-    cpm_find_package(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}" ${CPM_ARGS_FIND_PACKAGE_ARGUMENTS})
+  if(NOT CPM_ARGS_FORCE)
+    if(CPM_USE_LOCAL_PACKAGES OR CPM_LOCAL_PACKAGES_ONLY)
+      cpm_find_package(${CPM_ARGS_NAME} "${CPM_ARGS_VERSION}" ${CPM_ARGS_FIND_PACKAGE_ARGUMENTS})
 
-    if(CPM_PACKAGE_FOUND)
-      cpm_export_variables(${CPM_ARGS_NAME})
-      return()
-    endif()
+      if(CPM_PACKAGE_FOUND)
+        cpm_export_variables(${CPM_ARGS_NAME})
+        return()
+      endif()
 
-    if(CPM_LOCAL_PACKAGES_ONLY)
-      message(
-        SEND_ERROR
-          "${CPM_INDENT} ${CPM_ARGS_NAME} not found via find_package(${CPM_ARGS_NAME} ${CPM_ARGS_VERSION})"
-      )
+      if(CPM_LOCAL_PACKAGES_ONLY)
+        message(
+          SEND_ERROR
+            "${CPM_INDENT} ${CPM_ARGS_NAME} not found via find_package(${CPM_ARGS_NAME} ${CPM_ARGS_VERSION})"
+        )
+      endif()
     endif()
   endif()
 
@@ -713,9 +717,15 @@ function(CPMAddPackage)
     get_filename_component(download_directory ${download_directory} ABSOLUTE)
     list(APPEND CPM_ARGS_UNPARSED_ARGUMENTS SOURCE_DIR ${download_directory})
 
-    file(LOCK ${download_directory}/../cmake.lock)
+    if(CPM_SOURCE_CACHE)
+      file(LOCK ${download_directory}/../cmake.lock)
+    endif()
 
     if(EXISTS ${download_directory})
+      if(CPM_SOURCE_CACHE)
+        file(LOCK ${download_directory}/../cmake.lock RELEASE)
+      endif()
+
       cpm_store_fetch_properties(
         ${CPM_ARGS_NAME} "${download_directory}"
         "${CPM_FETCHCONTENT_BASE_DIR}/${lower_case_name}-build"
@@ -733,9 +743,13 @@ function(CPMAddPackage)
       endif()
 
       cpm_add_subdirectory(
-        "${CPM_ARGS_NAME}" "${DOWNLOAD_ONLY}"
-        "${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}" "${${CPM_ARGS_NAME}_BINARY_DIR}"
-        "${CPM_ARGS_EXCLUDE_FROM_ALL}" "${CPM_ARGS_OPTIONS}"
+        "${CPM_ARGS_NAME}"
+        "${DOWNLOAD_ONLY}"
+        "${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}"
+        "${${CPM_ARGS_NAME}_BINARY_DIR}"
+        "${CPM_ARGS_EXCLUDE_FROM_ALL}"
+        "${CPM_ARGS_SYSTEM}"
+        "${CPM_ARGS_OPTIONS}"
       )
       set(PACKAGE_INFO "${PACKAGE_INFO} at ${download_directory}")
 
@@ -783,20 +797,23 @@ function(CPMAddPackage)
       "${CPM_ARGS_NAME}" "${CPM_ARGS_VERSION}" "${PACKAGE_INFO}" "${CPM_ARGS_UNPARSED_ARGUMENTS}"
     )
     cpm_fetch_package("${CPM_ARGS_NAME}" populated)
+    if(CPM_SOURCE_CACHE AND download_directory)
+      file(LOCK ${download_directory}/../cmake.lock RELEASE)
+    endif()
     if(${populated})
       cpm_add_subdirectory(
-        "${CPM_ARGS_NAME}" "${DOWNLOAD_ONLY}"
-        "${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}" "${${CPM_ARGS_NAME}_BINARY_DIR}"
-        "${CPM_ARGS_EXCLUDE_FROM_ALL}" "${CPM_ARGS_OPTIONS}"
+        "${CPM_ARGS_NAME}"
+        "${DOWNLOAD_ONLY}"
+        "${${CPM_ARGS_NAME}_SOURCE_DIR}/${CPM_ARGS_SOURCE_SUBDIR}"
+        "${${CPM_ARGS_NAME}_BINARY_DIR}"
+        "${CPM_ARGS_EXCLUDE_FROM_ALL}"
+        "${CPM_ARGS_SYSTEM}"
+        "${CPM_ARGS_OPTIONS}"
       )
     endif()
     cpm_get_fetch_properties("${CPM_ARGS_NAME}")
   endif()
 
-  if(EXISTS ${download_directory}/../cmake.lock)
-    file(LOCK ${download_directory}/../cmake.lock RELEASE)
-  endif()
-
   set(${CPM_ARGS_NAME}_ADDED YES)
   cpm_export_variables("${CPM_ARGS_NAME}")
 endfunction()
@@ -942,13 +959,18 @@ function(
   SOURCE_DIR
   BINARY_DIR
   EXCLUDE
+  SYSTEM
   OPTIONS
 )
+
   if(NOT DOWNLOAD_ONLY AND EXISTS ${SOURCE_DIR}/CMakeLists.txt)
+    set(addSubdirectoryExtraArgs "")
     if(EXCLUDE)
-      set(addSubdirectoryExtraArgs EXCLUDE_FROM_ALL)
-    else()
-      set(addSubdirectoryExtraArgs "")
+      list(APPEND addSubdirectoryExtraArgs EXCLUDE_FROM_ALL)
+    endif()
+    if("${SYSTEM}" AND "${CMAKE_VERSION}" VERSION_GREATER_EQUAL "3.25")
+      # https://cmake.org/cmake/help/latest/prop_dir/SYSTEM.html#prop_dir:SYSTEM
+      list(APPEND addSubdirectoryExtraArgs SYSTEM)
     endif()
     if(OPTIONS)
       foreach(OPTION ${OPTIONS})
@@ -1079,6 +1101,7 @@ function(cpm_prettify_package_arguments OUT_VAR IS_IN_COMMENT)
       DOWNLOAD_COMMAND
       FIND_PACKAGE_ARGUMENTS
       NO_CACHE
+      SYSTEM
       GIT_SHALLOW
   )
   set(multiValueArgs OPTIONS)
diff --git a/web/content/docs/devguide/advanced/guix/index.md b/web/content/docs/devguide/advanced/guix/index.md
new file mode 100644
index 0000000000000000000000000000000000000000..243d14abebe682028eebb207f4817b4f41461b07
--- /dev/null
+++ b/web/content/docs/devguide/advanced/guix/index.md
@@ -0,0 +1,45 @@
++++
+date = "2023-07-20"
+title = "Build with GNU Guix"
+author = "Lars Bilke"
+weight = 1069
+
+[menu]
+  [menu.devguide]
+    parent = "advanced"
++++
+
+<div class='note'>
+
+### <i class="far fa-info-circle"></i> Warning
+
+This page and ogs builds with GNU Guix are currently work-in-progress!
+
+</div>
+
+[GNU Guix](https://guix.gnu.org) is a distribution of the GNU operating system but also a package manager. You can use it to create bit-by-bit reproducible (Linux) binaries of `ogs`. The package definitions are defined in [`guix.scm`](https://gitlab.opengeosys.org/ogs/ogs/-/blob/master/guix.scm). `guix` is currently installed on `envinf3`.
+
+## Building
+
+```bash
+guix build -f guix.scm                     # builds ogs serial config
+guix build -L $PWD/.guix/modules ogs-ssd   # SteadyStateDiffuion process only
+guix build -L $PWD/.guix/modules ogs-petsc # ogs petsc config
+```
+
+## Developing
+
+```bash
+guix shell
+# Now in guix shell with all dependencies installed:
+export CMAKE_PRESET_BUILD_DIR_PREFIX=guix/ # presets then create e.g. ../build/guix/release
+cmake --preset release -DOGS_BUILD_PROCESSES=SteadyStateDiffusion
+cmake --build --preset release
+```
+
+## Links
+
+- [`guix build`](https://guix.gnu.org/manual/en/html_node/Invoking-guix-build.html)-reference
+- [`guix shell`](https://guix.gnu.org/manual/en/html_node/Invoking-guix-shell.html)-reference
+- [`guix install`](https://guix.gnu.org/manual/en/html_node/Invoking-guix-install.html)-reference
+- [Blog: The ultimate guide to software development with Guix](https://guix.gnu.org/en/blog/2023/from-development-environments-to-continuous-integrationthe-ultimate-guide-to-software-development-with-guix/)