diff --git a/.gitignore b/.gitignore
index a2b26ad745757ecc69efd60ce3ed38a0a252e2bd..ee1732cf71e0ce9fef986b5f992676678e481b3f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,7 @@ packages
 jami_*.tar.gz
 Makefile.packaging.distro_targets
 repositories
+tarballs.manifest
 manual-download
 .docker-image-*
 
diff --git a/Makefile b/Makefile
index 78e6a8bd636d5246ad99988f5b278a76422e88d1..bd31c3700fb345ff5c8a36d67cbd441de0d031f0 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
 # -*- mode: makefile; -*-
-# Copyright (C) 2016-2019 Savoir-faire Linux Inc.
+# Copyright (C) 2016-2021 Savoir-faire Linux Inc.
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -54,20 +54,44 @@ CURRENT_GID:=$(shell id -g)
 .PHONY: release-tarball
 release-tarball: $(RELEASE_TARBALL_FILENAME)
 
-$(RELEASE_TARBALL_FILENAME):
-	# Fetch tarballs
-	mkdir -p daemon/contrib/native
+# 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 && \
 	cd daemon/contrib/native && \
-	    ../bootstrap && make list && \
-	    make fetch-all -j || make fetch-all || make fetch-all
+	../bootstrap && \
+        $(MAKE) list && \
+        $(MAKE) fetch -j && \
+	$(MAKE) --silent list-tarballs > $(CURDIR)/$@
 	rm -rf daemon/contrib/native
 
-	cd $(TMPDIR) && \
-	    tar -C $(CURDIR)/.. \
-	        --exclude-vcs \
-	        -zcf $(RELEASE_TARBALL_FILENAME) \
-	        $(shell basename $(CURDIR)) && \
-	    mv $(RELEASE_TARBALL_FILENAME) $(CURDIR)
+# 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.)
+$(RELEASE_TARBALL_FILENAME): tarballs.manifest
+# Prepare the sources of the top repository and relevant submodules.
+	rm -f "$@"
+	mkdir $(TMPDIR)/ring-project
+	git archive HEAD | tar xf - -C $(TMPDIR)/ring-project
+	for m in daemon lrc client-gnome; do \
+		(cd "$$m" && git archive --prefix "$$m/" HEAD \
+			| tar xf - -C $(TMPDIR)/ring-project); \
+	done
+# Create the base archive.
+	tar --create --file $(TMPDIR)/ring-project.tar $(TMPDIR)/ring-project \
+		--transform 's,.*/ring-project,ring-project,'
+# Append the cached tarballs listed in the manifest.
+	tar --append --file $(TMPDIR)/ring-project.tar \
+		--files-from $< \
+		--transform 's,^.*/,ring-project/daemon/contrib/tarballs/,'
+	gzip $(TMPDIR)/ring-project.tar
+	mv $(TMPDIR)/ring-project.tar.gz "$@"
+	rm -rf $(TMPDIR)
 
 #######################
 ## Packaging targets ##