How to setup an offline Ubuntu repository on an Ubuntu machine not connected to the internet
The following procedure is useful if you have an airgapped device which is not connected to the internet and you would like to update it or simply to install something new from the repository. It is also useful on fresh installs if you have limited network connectivity or it is simply slow.
In the tutorial I am working with repository for Ubuntu Kinetic and I am using riscv64 architecture, however this tutorial will work for all modern Ubuntu releases and all officially supported architectures.
The first tool requried is aptly.
Aptly is avaliable in the Ubuntu repository:
sudo apt install aptly
Configuration
Save the configuration file in $HOME/.aptly.conf .
This example configuration file I am using is using the riscv64 architecture. Use the architecture you require, presumably amd64. I have disabled the GPG check because it is not required and makes all of this much harder to configure.
{
"rootDir": "/home/$USER/.aptly",
"downloadConcurrency": 16,
"downloadSpeedLimit": 0,
"architectures": ["riscv64"],
"dependencyFollowSuggests": false,
"dependencyFollowRecommends": false,
"dependencyFollowAllVariants": false,
"dependencyFollowSource": false,
"dependencyVerboseResolve": false,
"gpgDisableSign": true,
"gpgDisableVerify": true,
"gpgProvider": "gpg",
"downloadSourcePackages": false,
"skipLegacyPool": true,
"ppaDistributorID": "ubuntu",
"ppaCodename": "",
"skipContentsPublishing": false,
"FileSystemPublishEndpoints": {},
"S3PublishEndpoints": {},
"SwiftPublishEndpoints": {}
}
Download the repository
Downloading is done with “aptly mirror update” command. The main repository will take about 5.5GB of data, while whole repository (universe multiverse, …) will take over 80GB. In this example I am only downloading the main repository which containes basics like build-essentials and dkms.
aptly mirror create ubuntu-kinetic http://ports.ubuntu.com/ubuntu-ports/ kinetic main
aptly mirror update ubuntu-kinetic
Now this data needs to be made into something useful:
aptly snapshot create localrepo from mirror ubuntu-kinetic
aptly publish snapshot -distribution kinetic -architectures="riscv64" localrepo
This will create public directory you can use as local repo. The public directory will look like this:
.
├── dists
│ └── kinetic
│ ├── Contents-riscv64.gz
│ ├── main
│ │ ├── binary-riscv64
│ │ │ ├── Packages
│ │ │ ├── Packages.bz2
│ │ │ ├── Packages.gz
│ │ │ └── Release
│ │ └── Contents-riscv64.gz
│ └── Release
└── pool
└── main
├── a
│ ├── aalib
│ │ ├── libaa1_1.4p5-50build1_riscv64.deb
│ │ └── libaa1-dev_1.4p5-50build1_riscv64.deb
│ ├── abseil
│ │ ├── libabsl20210324_0~20210324.2-4ubuntu1_riscv64.deb
│ │ └── libabsl-dev_0~20210324.2-4ubuntu1_riscv64.deb
│ ├── accountsservice
│ │ ├── accountsservice_22.08.8-1ubuntu1_riscv64.deb
│ │ ├── gir1.2-accountsservice-1.0_22.08.8-1ubuntu1_riscv64.deb
│ │ ├── libaccountsservice0_22.08.8-1ubuntu1_riscv64.deb
│ │ ├── libaccountsservice-dev_22.08.8-1ubuntu1_riscv64.deb
│ │ └── libaccountsservice-doc_22.08.8-1ubuntu1_all.deb
│ ├── acct
│ │ └── acct_6.6.4-5_riscv64.deb
│ ├── acl
│ │ ├── acl_2.3.1-1_riscv64.deb
│ │ ├── libacl1_2.3.1-1_riscv64.deb
│ │ └── libacl1-dev_2.3.1-1_riscv64.deb
│ ├── acpid
│ │ └── acpid_2.0.33-2ubuntu1_riscv64.deb
│ ├── adcli
│ │ └── adcli_0.9.1-1ubuntu2_riscv64.deb
│ ├── adduser
│ │ └── adduser_3.121ubuntu1_all.deb
│ ├── adsys
│ │ └── adsys_0.9.2_riscv64.deb
│ ├── advancecomp
│ │ └── advancecomp_2.3-1_riscv64.deb
│ ├── adwaita-icon-theme
│ │ └── adwaita-icon-theme_41.0-1ubuntu1_all.deb
...
Move the public directory to a ext4-formatted USB drive and mount it to /media/repo.
Add the local repository in your sources list
Backup the old sources.list file:
sudo mv /etc/apt/sources.list /etc/apt/sources.list.old
Then make new sources.list:
deb [Trusted=yes] file:///media/repo SuiteCodename main restricted universe multiverse
Where:
- SuiteCodename is jammy, kinetic, focal, bionic …
- You can include some or all the components ( main, multiverse, restricted, universe).
- [Trusted=yes] makes it skip the GPG check, which is needed because there are no signatures.
apt-get away
Try “sudo apt-get update” to see if apt understands the local repository. If all goes well, you can now use the local repository and make system updates.