A simple toolkit for installing software on Ubuntu systems without internet access. Download packages and Docker images on an online machine, transfer via USB, and install on your air-gapped system.
On your online machine:
chmod +x offline_download.sh
./offline_download.sh
# Follow prompts to download packages or Docker imagesOn your offline machine:
chmod +x offline_install.sh
sudo ./offline_install.sh
# Select which bundle(s) to installThis toolkit solves a common problem: installing software on systems that have no internet access.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β WORKFLOW DIAGRAM β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β ONLINE MACHINE OFFLINE MACHINE β
β ββββββββββββββ βββββββββββββββ β
β β
β 1. Run offline_download.sh 4. Run offline_install.sh β
β β β β
β βΌ βΌ β
β 2. Downloads packages ββββΊ 5. Installs packages β
β or Docker images USB or loads Docker images β
β β drive β β
β βΌ βΌ β
β 3. Creates setup_* folder 6. Software ready to use! β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
| Script | Purpose |
|---|---|
offline_download.sh |
Downloads .deb packages with all dependencies, or saves Docker images to .tar archives |
offline_install.sh |
Installs the downloaded packages and loads Docker images on the target system |
- Air-gapped networks: Secure environments with no external connectivity
- Remote deployments: Field installations where internet is unavailable
- Embedded systems: Headless devices requiring offline setup
- Controlled environments: Systems where direct internet access is restricted
- Batch deployments: Prepare once, deploy to multiple offline machines
| Requirement | Notes |
|---|---|
| Ubuntu/Debian system | Uses apt package management |
apt-rdepends |
Required - Install with sudo apt install apt-rdepends |
wget |
Optional but recommended for fallback downloads |
docker |
Only needed if downloading Docker images |
| Internet access | To download packages/images |
| Removable storage | USB drive or similar for transfer |
| Requirement | Notes |
|---|---|
| Ubuntu/Debian system | Same or compatible version as online machine |
dpkg and apt-get |
Pre-installed on Ubuntu |
docker |
Only needed if loading Docker images |
sudo access |
Required for installation |
Important: The offline machine should run the same Ubuntu version (or compatible) as the online machine to ensure package compatibility.
-
Prepare your online machine
First, ensure you have
apt-rdependsinstalled:sudo apt-get update sudo apt-get install apt-rdepends
-
Copy scripts to your USB drive
Copy both scripts to your USB drive's root directory.
-
Run the download script
cd /media/your-usb-drive chmod +x offline_download.sh ./offline_download.sh -
Select option 1 for .deb packages
-
Enter package names when prompted
- Space-separated:
nginx curl vim - Or comma-separated:
nginx, curl, vim
- Space-separated:
-
Review the dependency list and confirm
The script shows all packages that will be downloaded (including dependencies).
-
Wait for download to complete
A folder named
setup_<packages>will be created containing all.debfiles.
-
Ensure Docker is running on your online machine
docker info
-
Run the download script
./offline_download.sh
-
Select option 2 for Docker images
-
Enter image names when prompted
Examples:
nginx:latestpostgres:15 redis:7myregistry.com/myapp:v1.2.3
-
Wait for pull and save
A folder named
setup_docker_<images>will be created containing a.tararchive.
-
Connect USB drive to the offline machine
-
Navigate to the USB drive
cd /media/your-usb-drive -
Run the install script as root
sudo ./offline_install.sh
-
Select bundles to install
The script displays all available
setup_*folders:Available setup bundles to install/load: 1) nginx_curl 2) docker_postgres_redis a) Install/Load ALL bundles Enter numbers to process (e.g. 1 2), or 'a' for all: -
Wait for installation
The script will:
- Install all
.debfiles withdpkg - Load all Docker images with
docker load - Attempt to fix any dependency issues
- Install all
On online machine:
$ ./offline_download.sh
What would you like to download?
1) .deb packages only
2) Docker images only
Enter choice [1-2]: 1
Enter package names (space- or comma-separated): nginx
Updating apt cache...
Resolving dependencies...
Will attempt to download these packages:
β’ nginx
β’ libnginx-mod-http-geoip2
β’ nginx-common
β’ nginx-core
... (additional dependencies)
Proceed? [y/N] y
Downloading .deb packages...
Download complete!
Files are in: /media/usb/setup_nginxOn offline machine:
$ sudo ./offline_install.sh
Available setup bundles to install/load:
1) nginx
Enter numbers to process (e.g. 1 2), or 'a' for all: 1
Processing bundle: nginx
Installing .deb packages...
Fixing package dependencies (offline-safe)...
All done!
$ nginx -v
nginx version: nginx/1.24.0On online machine:
$ ./offline_download.sh
Enter choice [1-2]: 2
Enter Docker image names: postgres:15-alpine redis:7-alpine
Pulling Docker images...
β’ postgres:15-alpine
β’ redis:7-alpine
Saving all images into: docker_images_postgres_15-alpine_redis_7-alpine.tar
Download complete!On offline machine:
$ sudo ./offline_install.sh
Available setup bundles to install/load:
1) docker_postgres_15-alpine_redis_7-alpine
Enter numbers to process: 1
Processing bundle: docker_postgres_15-alpine_redis_7-alpine
Loading Docker images...
βͺ docker load -i docker_images_postgres_15-alpine_redis_7-alpine.tar
All done!
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
postgres 15-alpine abc123... 2 days ago 240MB
redis 7-alpine def456... 3 days ago 30MBIf you need both packages and Docker images, run the download script twice:
# First run - download packages
./offline_download.sh # Choose option 1, enter "docker.io containerd"
# Second run - download images
./offline_download.sh # Choose option 2, enter "nginx:alpine"Your USB will contain:
/media/usb/
βββ setup_docker.io_containerd/
β βββ docker.io_*.deb
β βββ containerd_*.deb
β βββ ... (dependencies)
βββ setup_docker_nginx_alpine/
β βββ docker_images_nginx_alpine.tar
βββ offline_download.sh
βββ offline_install.sh
Problem: The download script requires apt-rdepends to resolve dependencies.
Solution:
sudo apt-get update
sudo apt-get install apt-rdependsProblem: Docker daemon requires elevated privileges.
Solutions:
- Add your user to the docker group:
sudo usermod -aG docker $USER # Log out and back in
- Or the script will automatically use
sudofor Docker commands.
Problem: Some packages are "virtual" (meta-packages that don't exist on their own).
Solution: The script automatically finds real package providers. If a package is still skipped, manually identify and request the actual package name:
apt-cache showpkg <virtual-package-name>
# Look for "Reverse Provides" to find real packagesProblem: Some dependencies might be missing from the bundle.
Solutions:
- Ensure both machines run the same Ubuntu version
- Re-run the download with any missing packages added
- Check the output for "skipped" packages and download those separately
Problem: The .tar file might be corrupted or incomplete.
Solutions:
- Verify the file size matches between machines
- Re-download the images
- Ensure Docker daemon is running:
sudo systemctl start docker
Problem: The install script can't find any bundles.
Solution:
- Ensure you're running the script from the USB drive root
- Check that download completed successfully
- Verify folder names start with
setup_
Q: Can I download packages for a different Ubuntu version?
A: The downloaded packages are specific to your Ubuntu version and architecture. For best results, run the download script on a machine with the same Ubuntu version as your target.
Q: How much space do I need on my USB drive?
A: It depends on the packages. A simple tool like curl needs ~5MB with dependencies. Large applications like Docker can need 500MB+. Check available space before downloading.
Q: Can I update packages on an offline machine?
A: Yes! Re-run the download script on your online machine to get the latest versions, then transfer and re-install.
Q: Does this work with private Docker registries?
A: Yes, as long as you're logged into the registry on your online machine (docker login), you can pull and save private images.
Q: Can I use this for Debian (not Ubuntu)?
A: Yes, these scripts should work on any Debian-based system that uses apt and dpkg.
Q: What if some packages fail to download?
A: The script continues with remaining packages. Review the output for errors and retry failed packages separately if needed.
- Architecture-specific: Packages are downloaded for your current CPU architecture (amd64, arm64, etc.)
- Version-specific: Best results when online and offline machines run the same OS version
- No automatic updates: You must manually re-download to get newer package versions
- Single-mode downloads: Each run downloads either packages OR Docker images, not both simultaneously
- Ubuntu/Debian only: Designed for apt-based systems
-
Test on a similar system first - Before deploying to production, test the bundle on a non-critical machine with the same OS version.
-
Keep bundles organized - Use descriptive package names. The folder name will reflect what you downloaded.
-
Verify downloads - Check that all expected files are present before transferring to the offline machine.
-
Document what you download - Keep a record of package names and versions for future reference.
-
Use the same Ubuntu version - Package compatibility is best when both machines run identical Ubuntu versions.
MIT License - Feel free to use, modify, and distribute these scripts.
Found a bug or have a suggestion? Open an issue or submit a pull request on GitHub.