diff --git a/Jenkinsfile b/Jenkinsfile
index 3c22a775e17dd6238c9f47a5c79d768844eec679..4e14bb1d0567c2057d20a6f97237e431f9827f9e 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -35,30 +35,11 @@ See https://wiki.savoirfairelinux.com/wiki/Jenkins.jami.net#Configuration"
 
         stage('Generate release tarball') {
             steps {
-                // The bundled tarballs included in the release
-                // tarball depend on what is available on the host.
-                // To ensure it can be shared across all different
-                // GNU/Linux distributions, generate it in a minimal
-                // container.  Wget uses GnuTLS, which looks up its
-                // certs from /etc/ssl/certs.
-                sh '''
-                   #!/usr/bin/env bash
+                // Note: sourcing .bashrc is necessary to setup the
+                // environment variables used by Guix.
+                sh '''#!/usr/bin/env bash
                    test -f $HOME/.bashrc && . $HOME/.bashrc
-                   guix environment --container --network -E TARBALLS --share=$TARBALLS \
-                       --expose=$SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt --ad-hoc \
-                       coreutils \
-                       gcc-toolchain \
-                       git-minimal \
-                       grep \
-                       gzip \
-                       make \
-                       nss-certs \
-                       pkg-config \
-                       python \
-                       sed \
-                       tar \
-                       wget \
-                       xz -- make release-tarball
+                   make portable-release-tarball
                    '''
             }
         }
diff --git a/Makefile b/Makefile
index 88e679e45eb7c93ee5a3f2f63167233482a04bd9..4773d2415b80bde90623d706765c906319044f65 100644
--- a/Makefile
+++ b/Makefile
@@ -57,28 +57,47 @@ CURRENT_GID:=$(shell id -g)
 #############################
 ## Release tarball targets ##
 #############################
-.PHONY: release-tarball
-release-tarball: $(RELEASE_TARBALL_FILENAME)
+.PHONY: release-tarball purge-release-tarballs portable-release-tarball
+
+purge-release-tarballs:
+	rm -f jami_*.tar.* tarballs.manifest
+
+release-tarball:
+	rm -f "$(RELEASE_TARBALL_FILENAME)" tarballs.manifest
+	$(MAKE) "$(RELEASE_TARBALL_FILENAME)"
+
+# The bundled tarballs included in the release tarball depend on what
+# is available on the host.  To ensure it can be shared across all
+# different GNU/Linux distributions, generate it in a minimal
+# container.  Wget uses GnuTLS, which looks up its certs from
+# /etc/ssl/certs.
+guix-share-tarball-arg = $${TARBALLS:+"--share=$$TARBALLS"}
+portable-release-tarball:
+	command -v guix > /dev/null 2>&1 || \
+	  (echo 'guix' is required to build the '$@' target && exit 1) && \
+	guix environment --container --network \
+          --preserve=TARBALLS $(guix-share-tarball-arg) \
+          --expose=/usr/bin/env \
+          --expose=$$SSL_CERT_FILE \
+          --manifest=$(CURDIR)/guix/minimal-manifest.scm \
+          -- $(MAKE) release-tarball
+
+daemon/contrib/native/Makefile:
+	mkdir -p daemon/contrib/native && \
+	cd daemon/contrib/native && \
+	../bootstrap
 
 # Fetch the required contrib sources and copy them to
 # daemon/contrib/tarballs.  To use a custom tarballs cache directory,
 # export the TARBALLS environment variable.
-tarballs.manifest:
-	rm -rf daemon/contrib/native
-	mkdir -p daemon/contrib/native && \
+tarballs.manifest: daemon/contrib/native/Makefile
 	cd daemon/contrib/native && \
-	../bootstrap && \
-        $(MAKE) list && \
-        $(MAKE) fetch -j && \
-	$(MAKE) --silent list-tarballs > $(CURDIR)/$@
-	rm -rf daemon/contrib/native
-
-# Generate the release tarball.  Note: to avoid building 1+ GiB
-# tarball containing all the bundled libraries, only the required
-# tarballs are included.  This means the resulting release tarball
-# content depends on what libraries the host has installed.  To build
-# a single release tarball that can be used for any GNU/Linux machine,
-# it should be built in a minimal container.)
+	$(MAKE) list && \
+	$(MAKE) fetch -j && \
+	$(MAKE) --no-print-directory --silent list-tarballs > "$(CURDIR)/$@"
+
+# Generate the release tarball.  To regenerate a fresh tarball
+# manually clear the tarballs.manifest file.
 $(RELEASE_TARBALL_FILENAME): tarballs.manifest
 # Prepare the sources of the top repository and relevant submodules.
 	rm -f "$@"
diff --git a/guix/minimal-manifest.scm b/guix/minimal-manifest.scm
new file mode 100644
index 0000000000000000000000000000000000000000..f9c1f14a26dd6aa067e5f104006b0bcefc8bdd38
--- /dev/null
+++ b/guix/minimal-manifest.scm
@@ -0,0 +1,25 @@
+;;; To use with the GNU Guix package manager.
+;;; Available at https://guix.gnu.org/.
+;;;
+;;; Commentary:
+;;;
+;;; This Guix manifest can be used to create an environment that
+;;; satisfies the minimal requirements of the the contrib build system
+;;; of the daemon.  For example, it is used by the CI to build the
+;;; source release tarball in a controlled environment.
+
+(specifications->manifest
+ (list
+  "coreutils"
+  "gcc-toolchain"
+  "git-minimal"
+  "grep"
+  "gzip"
+  "make"
+  "nss-certs"
+  "pkg-config"
+  "python"
+  "sed"
+  "tar"
+  "wget"
+  "xz"))