Skip to content

Instantly share code, notes, and snippets.

@jeanlescure
Last active March 25, 2024 19:08
Show Gist options
  • Star 66 You must be signed in to star a gist
  • Fork 27 You must be signed in to fork a gist
  • Save jeanlescure/084dd6113931ea5a0fd9 to your computer and use it in GitHub Desktop.
Save jeanlescure/084dd6113931ea5a0fd9 to your computer and use it in GitHub Desktop.
Ubuntu/Debian Offline Repository Creation

Ubuntu/Debian Offline Repository Creation Gist

When I googled how to create my own offline repository of packages for use in an offline Ubuntu/Debian machine, the results were disheartening and the steps to be taken scattered all over the place.

The files within this gist will allow you to:

  • Download specific apt-get packages... with dependencies included!
  • Create a Packages.gz file so that you can add the repository folder you create to the target machine's /etc/apt/sources.list file.

Before using

This gist is comprised of 3 scripts:

  • dependencies.sh
  • getpkg.sh
  • mkrepo.sh

Be sure to make them executable by chmod'ing them.

Dependencies

There are two scripts within this gist which will aid you in creating your offline repo:

  • getpkg.sh
  • mkrepo.sh

The script getpkg.sh depends on the package apt-rdepends.

The script mkrepo.sh depends on the program dpkg-scanpackages which is part of the dpkg-dev package.

In order to install this dependencies simply run:

$ sudo ./dependencies.sh

Downloading packages

To download an apt-get package (including its dependencies) simply run:

$ ./getpkg.sh <package-name> <packages-directory>

where <package-name> is the name of the package you are trying to store locally and <packages-directory> is the path to the directory where you'll be storing the downloaded packages.

Example:

$ ./getpkg.sh build-essential /home/user/my-repo

WARNING: Since this script downloads not only the deb package, but its dependencies as well, be sure you have a decent amount of free hard-disk space since things can quickly escalate. For example, the package ubuntu-desktop when downloaded with dependencies and all, weighs well over 300MB. You have been warned.

Turning your packages directory into a repo

The following should only be done once, after having downloaded all the packages you deem necessary to be in your offline repository (as in, after having followed the steps in the Downloading packages section of this guide).

In order to transform the directory where you placed your repository's packages into an actual apt-get valid repo, just run:

$ ./mkrepo.sh <packages-directory>

where <packages-directory> is the path to the directory where you stored the downloaded packages.

Example:

$ ./mkrepo.sh /home/user/my-repo

Using your offline repo

Let's say you have a machine with no internet connection which runs Ubuntu, and you wish to install some apps not included in the provided apt-get repository.

You followed the steps in this guide and stored within a usb pen-drive a directory called my-repo, which contains the apps you want to install and a file named Packages.gz.

You plug this repo-wielding usb pen-drive into the offline Ubuntu machine, and you make sure to mount it to the route /media/repo-usb.

Now you can add the following line to the /etc/apt/sources.list file, in the offline Ubuntu machine:

deb [trusted=yes] file:/media/repo-usb/my-repo ./

Run the command:

$ sudo apt-get update

Et voilà! You can now sudo apt-get install your packages to your heart's content.

Collaborators

The contents and benefits of this gist have been made possible by:

#!/usr/bin/env bash
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root" 1>&2
exit 1
fi
apt-get update
apt-get install -y apt-rdepends dpkg-dev gzip
#!/usr/bin/env bash
function error_exit
{
echo "$1" 1>&2
echo "Usage: ./getpkg.sh <package-name> <packages-directory>" 1>&2
exit 1
}
PKG="$1"
PKGDIR="$2"
if [ -z "$PKG" ]; then
error_exit "No package name set!"
fi
if [ -z "$PKGDIR" ]; then
error_exit "No packages directory path set!"
fi
cd $PKGDIR
for i in $(apt-rdepends $PKG|grep -v "^ ")
do ! apt-get download $i
done
#!/usr/bin/env bash
function error_exit
{
echo "$1" 1>&2
echo "Usage: ./mkrepo.sh <packages-directory>" 1>&2
exit 1
}
PKGDIR="$1"
if [ -z "$PKGDIR" ]; then
error_exit "No packages directory path set!"
fi
cd $PKGDIR
dpkg-scanpackages ./ /dev/null | gzip -9c > ./Packages.gz
@Mohamad-Khayat
Copy link

Hi, I created a fork to update the source.list line to "deb [trusted=yes] file:/media/repo-usb/my-repo ./" to override the trust error.

@jeanlescure
Copy link
Author

Cheers @Mohamad-Khayat , I've gone ahead and edited the README to include your modification 👍

@percin
Copy link

percin commented Apr 5, 2021

Thank you very much for your hard work. It took a bit of work to make various adjustments, but eventually I was able to create a fully autonomous offline repo generator.

@lionelzeus
Copy link

Hi,

How do I download security updates for Ubuntu?
I was able to download individual packages but not sure how to pull down security updates for offline patching.

@jolinux
Copy link

jolinux commented Jan 22, 2022

Hello,
I use your scripts and download my packages months ago. I need yesterday a other packages and do the steps again.

Question: Can I update the packages from the first run ? Are all (new and old) packages autoupdate if I run a getpkg or dependencies later again ? -> Need a local repo with current sharing packages DEBIAN10 !!

Thank you for share your Tools

@jeanlescure
Copy link
Author

Hi @jolinux , thanks for the kind words. I'm sorry to say, no, the scripts here do not facilitate updating already downloaded packages, my usage of these has always been like a once or twice a year kind of thing for non-critical very basic raspberry pi installations. Only downloading what is more recent would require some version checking logic which in my case would take more time to write than what it takes me to just download everything from scratch.

I am aware that there's many situations where that is not ideal (i.e. using mobile data in hard-to-reach rural areas). By looking at comments and stars I assume these scripts are probably in the top search results for this topic, in order to keep helping the community I am always open to updating the scripts if a solution for how to update already downloaded packages is found. This includes adding credit to the author of the solution.

Cheers

@Danny3
Copy link

Danny3 commented Feb 2, 2022

Is there any way to download multiple packages, with their dependencies of course, instead of one by one?
To download a package with its dependencies I've already found a way with this command (where package-name is the package that we want):

sudo apt-get download $(apt-cache depends --recurse --no-recommends --no-suggests --no-conflicts --no-breaks --no-replaces --no-enhances package-name | grep "^\w" | sort -u)

@dlvalente
Copy link

Is there a way to download only packages which have been updated in a specific time window (E.G. last 60 days)?

@jolinux
Copy link

jolinux commented Oct 6, 2022

Info
A other way to do this (only german)

https://wiki.debianforum.de/Lokales_Repository

@Barafu
Copy link

Barafu commented Mar 12, 2023

Big thanks for that, saved my day.

Note: In my case, I had to unpack Packages.gz into just Packages before apt could read it.

@Koentekraafs
Copy link

Works for raspberi pi running raspberry pi OS?

@vignesh882
Copy link

When I try to download vim-gt3, I am getting following error,
E: Can't select candidate version from package fonts-freefont as it has no candidate
any help

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment