DEV Community

Cover image for Fast Large-file and LLM Downloads with aria2 on NVIDIA Jetson AGX Orin
Sergio Andres Usma
Sergio Andres Usma

Posted on

Fast Large-file and LLM Downloads with aria2 on NVIDIA Jetson AGX Orin

Abstract

This tutorial documents the configuration and use of aria2 to download very large files and LLM weight archives on an NVIDIA Jetson AGX Orin Developer Kit 64 GB running Ubuntu 22.04.5 LTS aarch64 with JetPack 6.2.2. It focuses on high-concurrency HTTPS downloads from Hugging Face and similar model repositories, with commands tuned for edge hardware, multi-gigabyte single-file models in GGUF or safetensors format, and the object storage redirect behavior common to modern model hosting platforms.

The guide covers robust resume strategies using .aria2 control files and session files that allow downloads to survive reboots, intermittent connectivity, and signed URL expiration. Failure scenarios encountered in practice — including HTTP 403 rate limits near completion, hash-like output filenames resulting from redirect chains, and missing control metadata — are addressed with safe, prescriptive recovery steps that avoid data corruption or accidental full re-downloads.

The document targets advanced Linux and Jetson users who regularly fetch multi-GB model artefacts and want a repeatable, resilient pattern for aria2 on ARM64. Readers will finish with a working installation, a set of reusable power commands, a reliable batch-resume workflow, and the knowledge to debug common failure modes without discarding already-downloaded data.


1. Hardware and software environment

The environment documented throughout this tutorial is an NVIDIA Jetson AGX Orin Developer Kit with 64 GB unified memory, running a standard JetPack 6.2.2 software stack on Ubuntu 22.04.5 LTS aarch64. This configuration represents a current-generation edge AI development system with sufficient CPU cores, RAM, and storage throughput to benefit from aria2's parallel download capabilities. The commands and flag values in subsequent sections are validated against this environment.

Component Version / Value
Hardware NVIDIA Jetson AGX Orin Developer Kit 64 GB
OS Ubuntu 22.04.5 LTS aarch64
Kernel 5.15.185-tegra
L4T 36.5.0
JetPack 6.2.2
CUDA 12.6
cuDNN 9.3
TensorRT 10.3

Table 1 — Jetson AGX Orin software stack

The tutorial assumes that network routing, DNS, and internet connectivity to Hugging Face are already functional on the device. No proxy or VPN configuration is assumed, although aria2 supports those if needed. Storage is assumed to be NVMe or SSD formatted as ext4, which affects the recommended file allocation strategy discussed in section 6.


2. Installing aria2

aria2 is available from the official Ubuntu 22.04 aarch64 package repositories and requires no external PPA or manual build on this platform.

sudo apt update
sudo apt install -y aria2
aria2c -v
Enter fullscreen mode Exit fullscreen mode

aria2c -v prints version details and build flags, confirming that the binary is functional and correctly linked. If the command is not found, verify that /usr/bin is in PATH. On a standard Jetson Ubuntu installation, no adjustments are required.

Create dedicated directories for model files and their associated .aria2 control files before starting any downloads. Co-locating them in stable directories is essential for reliable resume behavior, as aria2 expects the data file and its sidecar to share the same directory and base name.

mkdir -p ~/models
mkdir -p ~/downloads
Enter fullscreen mode Exit fullscreen mode

Moving or renaming a data file after a partial download breaks the association aria2 relies on to continue from the correct offset. Establish these directories once and use them consistently across all aria2 invocations.


3. Fast single-file downloads from Hugging Face

3.1 Core throughput flags: -x, -s, and -k

For a single large file, aria2 opens multiple HTTP connections and divides the target into segments that are fetched concurrently. Three flags control this behavior:

  • -x N / --max-connection-per-server=N: number of parallel HTTP connections opened to the server.
  • -s N / --split=N: number of segments the file is divided into for parallel download.
  • -k SIZE / --min-split-size=SIZE: minimum size per segment (e.g., 64M); prevents excessive small chunks for large files.

The URL must always be the last positional argument. A common mistake is placing -s immediately before the URL with no numeric value between them, which causes aria2 to interpret the URL as the split count and fail silently.

Correct usage for a Hugging Face GGUF file:

aria2c -x 16 -s 16 \
  "https://huggingface.co/unsloth/gemma-4-31B-it-GGUF/resolve/main/gemma-4-31B-it-Q4_K_M.gguf?download=true"
Enter fullscreen mode Exit fullscreen mode

If the server returns HTTP 429 responses or imposes rate limits, reduce concurrency:

aria2c -x 8 -s 8 \
  "https://huggingface.co/unsloth/gemma-4-31B-it-GGUF/resolve/main/gemma-4-31B-it-Q4_K_M.gguf?download=true"
Enter fullscreen mode Exit fullscreen mode

Example of download command to download gemma-4-26B-A4B-it-UD-Q4_K_M.gguf

aria2c \
  -c \
  -x8 -s8 \
  -k32M \
  --retry-wait=10 \
  --max-tries=0 \
  --file-allocation=none \
  --summary-interval=60 \
  -o gemma-4-26B-A4B-it-UD-Q4_K_M.gguf \
  'https://huggingface.co/unsloth/gemma-4-26B-A4B-it-GGUF/resolve/main/gemma-4-26B-A4B-it-UD-Q4_K_M.gguf?download=true' 
Enter fullscreen mode Exit fullscreen mode

3.2 Power command template for large model downloads

The following command is the recommended baseline for large model downloads. It combines high concurrency with resilient retry behavior, explicit resume support, and a stable output filename.

aria2c -c -x16 -s16 -k64M \
  --retry-wait=5 --max-tries=0 \
  --file-allocation=none \
  --summary-interval=60 \
  -d ~/models \
  -o gemma-4-31B-it-Q4_K_M.gguf \
  "https://huggingface.co/unsloth/gemma-4-31B-it-GGUF/resolve/main/gemma-4-31B-it-Q4_K_M.gguf?download=true"
Enter fullscreen mode Exit fullscreen mode

Flag-by-flag explanation:

  • -c / --continue=true: resume an existing partial file if the .aria2 control file is present.
  • -x16 / -s16: 16 parallel connections and 16 file segments for maximum throughput on a fast link.
  • -k64M: 64 MB minimum segment size; reduces the number of chunks for very large files.
  • --retry-wait=5: pause 5 seconds before each retry on transient errors.
  • --max-tries=0: retry indefinitely; aria2 will not give up until stopped manually.
  • --file-allocation=none: skip pre-allocation of the full file size, avoiding a blocking write at startup on Jetson NVMe storage.
  • -d ~/models: explicit target directory.
  • -o <filename>: explicit output filename, preventing query-string characters or hash-like object keys from appearing in the filename on disk.

For throttled or unstable connections, use the conservative variant:

aria2c -c -x8 -s8 -k16M \
  --retry-wait=10 --max-tries=0 \
  --file-allocation=none \
  -d ~/models \
  "https://huggingface.co/.../model.gguf?download=true"
Enter fullscreen mode Exit fullscreen mode

This reduces pressure on the server while still delivering substantially better throughput than a single connection.


4. Resume mechanics and .aria2 Control Files

4.1 How aria2 resume works

For every active download, aria2 creates a binary control file alongside the data file using the naming convention <target-filename>.aria2. Downloading model.gguf produces both model.gguf and model.gguf.aria2 in the output directory. The control file tracks segment byte offsets, checksums, and download state. Without it, aria2 cannot determine which byte ranges are valid and cannot safely resume.

If the same aria2 command is re-run from the same directory with the same output filename, aria2 detects the existing data file and its .aria2 sidecar and continues from the last recorded position. The -c flag makes this behavior explicit and causes aria2 to abort rather than silently overwrite when a safe resume is not possible.

# First run — interrupted partway through
aria2c -c -x16 -s16 -k64M -o model.gguf "https://huggingface.co/.../model.gguf"

# Second run — resumes from the interrupted position
aria2c -c -x16 -s16 -k64M -o model.gguf "https://huggingface.co/.../model.gguf"
Enter fullscreen mode Exit fullscreen mode

To enforce strict resume-or-abort behavior rather than a silent restart:

aria2c --always-resume=true -c "https://example.com/bigfile.iso"
Enter fullscreen mode Exit fullscreen mode

4.2 Missing .aria2 control file

If aria2 reports errorCode=13 or a message containing "file exists but .aria2 does not exist", the data file is present but the control file has been lost.

  • If the data file is complete and passes an integrity check (e.g., SHA-256 matches the repository-published hash), it can be kept and removed from any pending URL or session lists.
  • If the data file is incomplete and the .aria2 file is gone, aria2 has no record of which byte ranges were successfully written. The safest recovery is to delete both the partial data file and any remnant .aria2 file, then restart the download from scratch for that specific file.

Do not attempt to resume an incomplete file without its control file. The resulting output may silently contain duplicate or missing byte ranges.

4.3 Resuming with a new signed URL

Hugging Face and similar hosts issue time-limited signed URLs. If a partial download's original URL has expired, resume is still possible provided:

  • The output file name and directory path are unchanged.
  • The new URL resolves to the same file content.
aria2c -c --auto-file-renaming=false \
  -d ~/models -o model.gguf \
  "https://new-signed-url..."
Enter fullscreen mode Exit fullscreen mode

The --auto-file-renaming=false flag prevents aria2 from creating a renamed copy (e.g., model.gguf.1) when it detects an existing file. Instead, aria2 reuses the existing partial file and its .aria2 control file and continues from the recorded position.


5. Batch downloads and session files

5.1 URL list with session management

When downloading multiple files — such as a full safetensors shard set or several GGUF quantization variants — use a URL list file and a session file to enable batch resume. Create urls.txt with one URL per line:

https://huggingface.co/.../model-00001-of-00037.safetensors
https://huggingface.co/.../model-00002-of-00037.safetensors
https://huggingface.co/.../model-00003-of-00037.safetensors
Enter fullscreen mode Exit fullscreen mode

Start the batch with session tracking enabled:

aria2c -i urls.txt \
  --save-session=aria2-session.txt \
  --save-session-interval=60 \
  -c -x8 -s8 -k16M \
  -d ~/models
Enter fullscreen mode Exit fullscreen mode
  • -i urls.txt: read download targets from the URL list file.
  • --save-session=aria2-session.txt: write all active and incomplete download state to the session file.
  • --save-session-interval=60: flush the session file to disk every 60 seconds, limiting lost progress on an abrupt stop.
  • -c: resume any partial files found in the target directory.

After a reboot or manual stop, resume the entire batch:

aria2c --input-file=aria2-session.txt \
  --save-session=aria2-session.txt \
  -c
Enter fullscreen mode Exit fullscreen mode

--input-file reloads all entries from the session file. Completed downloads are automatically dropped from the next session write. Adding --force-save=true retains completed entries for audit purposes, but requires manual pruning of the session file as the download set grows.

5.2 Persistent single-session workflow

A single session file can serve as both input and output, providing a self-maintaining queue of unfinished downloads across multiple aria2 invocations.

touch aria2-session.txt
aria2c --input-file=aria2-session.txt \
  --save-session=aria2-session.txt \
  --save-session-interval=30 \
  -c -x8 -s8 -k16M \
  -d ~/downloads
Enter fullscreen mode Exit fullscreen mode

New URLs can be added to the queue at any time by running a separate aria2c -i urls.txt ... --save-session=aria2-session.txt invocation. The session file accumulates all unfinished tasks and the next resume run picks them all up automatically.


6. Jetson-specific configuration and filesystem Considerations

6.1 Recommended baseline flags for Jetson AGX Orin

The Jetson AGX Orin has fast CPU cores and ample RAM, but disk throughput and storage capacity may be shared across concurrent inference workloads. The following practices are tuned for this profile:

  • Use a dedicated directory per model project (~/models, ~/hf_cache) to keep .aria2 control files co-located with their data files and avoid cross-directory confusion.
  • Prefer --file-allocation=none for fast startup. Switch to falloc only when pre-allocation is explicitly needed for fragmentation control on large multi-GB artefacts.
  • Start with -x8 -s8 and increase to 16 if the connection and server support it without triggering rate limiting.
  • Always include -c for any file larger than a few hundred megabytes to guard against accidental restarts.

Add a shell alias to ~/.bashrc to standardize the baseline:

echo "alias aria2fast='aria2c -c -x8 -s8 -k16M --file-allocation=none --summary-interval=30'" >> ~/.bashrc
source ~/.bashrc
Enter fullscreen mode Exit fullscreen mode

Usage with the alias:

aria2fast -d ~/models -o model.gguf "https://huggingface.co/.../model.gguf?download=true"
Enter fullscreen mode Exit fullscreen mode

A Hugging Face-specific alias with longer retry delays handles the backend's rate limiting more gracefully:

echo "alias hfaria='aria2c -c -x8 -s8 -k32M --retry-wait=10 --max-tries=0 --file-allocation=none --summary-interval=60'" >> ~/.bashrc
source ~/.bashrc
Enter fullscreen mode Exit fullscreen mode

6.2 File allocation on Jetson NVMe

On the Jetson NVMe (ext4 with extents), --file-allocation=falloc pre-allocates the full file using fallocate(2), which is fast and reduces fragmentation for multi-GB files. On slower or older filesystems, --file-allocation=none avoids a blocking write pass at startup.

aria2c -c -x8 -s8 -k32M \
  --file-allocation=falloc \
  -d ~/models \
  "https://huggingface.co/.../model.gguf?download=true"
Enter fullscreen mode Exit fullscreen mode

Monitor available storage before long downloads with df -h. An out-of-space condition frequently manifests as repeated failures at the same completion percentage, which can be misread as a network or server error.


7. Filename issues from redirect chains

7.1 Why downloads receive hash-like filenames

When downloading from a Hugging Face resolve URL, the server redirects through an internal S3-style backend (cas-bridge.xethub.hf.co or similar object storage). The final HTTP response path contains an opaque SHA-like object key rather than the human-readable model filename. If no explicit output name is provided with -o, aria2 saves the file using that object key as the filename, producing output such as:

c56b8f0416a453a53aace7bef4a088a2c2db33c3b8a4eda949a380c214420b31
Enter fullscreen mode Exit fullscreen mode

The fix is to always specify -o with the intended filename. This flag forces the output name regardless of redirects or Content-Disposition headers:

cd ~/models

aria2c -c -x8 -s8 -k32M \
  --file-allocation=none \
  -o gemma-4-31B-it-Q4_K_M.gguf \
  "https://huggingface.co/unsloth/gemma-4-31B-it-GGUF/resolve/main/gemma-4-31B-it-Q4_K_M.gguf?download=true"
Enter fullscreen mode Exit fullscreen mode

7.2 Renaming an existing hash-named partial file

If a large partial download was already saved under a hash name, it can be renamed without discarding the downloaded data. Both the data file and its .aria2 sidecar must be renamed to matching names simultaneously:

cd ~/models

mv c56b8f0416a453a53aace7bef4a088a2c2db33c3b8a4eda949a380c214420b31 \
   gemma-4-31B-it-Q4_K_M.gguf

mv c56b8f0416a453a53aace7bef4a088a2c2db33c3b8a4eda949a380c214420b31.aria2 \
   gemma-4-31B-it-Q4_K_M.gguf.aria2
Enter fullscreen mode Exit fullscreen mode

After renaming, re-run the standard aria2 command with -o gemma-4-31B-it-Q4_K_M.gguf from the same directory. aria2 will locate the renamed pair and resume only the missing segments.


8. Failure modes and recovery

8.1 HTTP 403 errors during download (errorCode=22)

Error lines of the form errorCode=22 … status=403 indicate that individual HTTP segment requests were rejected by the backend. This occurs most commonly near the end of a long download from Hugging Face for two reasons:

  • Signed S3 URLs in the redirect chain expire mid-download on very large or slow-connection transfers.
  • High concurrency (-x16 -s16) triggers per-connection rate limiting on popular models.

When errorCode=22 appears but the download ultimately reports stat|OK, aria2 recovered and retried successfully. To reduce the frequency of these errors:

aria2c -c -x8 -s8 -k32M \
  --retry-wait=10 --max-tries=0 \
  --file-allocation=none \
  -o gemma-4-31B-it-Q4_K_M.gguf \
  "https://huggingface.co/unsloth/gemma-4-31B-it-GGUF/resolve/main/gemma-4-31B-it-Q4_K_M.gguf?download=true"
Enter fullscreen mode Exit fullscreen mode

Lower -x/-s values reduce the number of simultaneous signed segment requests in flight. Combined with --retry-wait=10 and --max-tries=0, aria2 waits calmly between retries rather than hammering the backend.

8.2 Persistent failures at a fixed byte offset

When a download fails repeatedly at the same percentage or offset:

  • Reduce -x and -s to lower concurrent byte-range requests.
  • Increase --retry-wait (e.g., --retry-wait=30) and keep --max-tries=0 to allow extended retry cycles.
  • Check for local storage or filesystem errors with dmesg and journalctl -xe. Write errors on Jetson NVMe can present as download failures at the application layer.
  • If the .aria2 control file is corrupted and resume fails consistently, delete both the partial data file and the .aria2 file, then restart that specific download only — not the entire batch.

8.3 Quick command reference

Use case Command
Fast single model download aria2c -c -x16 -s16 -k64M --file-allocation=none -d ~/models -o FILE "URL"
Conservative single model aria2c -c -x8 -s8 -k16M --file-allocation=none -d ~/models -o FILE "URL"
Resume single file aria2c -c -x8 -s8 -o FILE "URL" (run from same dir, .aria2 present)
Batch from URL list aria2c -i urls.txt --save-session=aria2-session.txt -c -x8 -s8 -d ~/models
Resume batch via session aria2c --input-file=aria2-session.txt --save-session=aria2-session.txt -c
New signed URL for partial aria2c -c --auto-file-renaming=false -d DIR -o FILE "NEW_URL"
Retain completed in session Add --force-save=true; prune session file manually as needed

Table 2 — aria2 command reference for Jetson AGX Orin


9. Practical outcomes

  • Established a correct and efficient aria2 command pattern for large Hugging Face model downloads on Jetson AGX Orin, including proper flag ordering for -x, -s, and -k, and the mandatory use of -o to avoid hash-like filenames from object storage redirects.
  • Documented resume mechanics using .aria2 control files, the -c flag, and --always-resume=true, with explicit guidance on what to do when the control file is missing or the data file has been renamed.
  • Provided a signed-URL resume pattern using --auto-file-renaming=false that handles expiring links without restarting partial downloads.
  • Defined batch download patterns using URL list files and persistent session files (--save-session, --input-file) for multi-shard model repositories such as safetensors split sets.
  • Captured Jetson-specific defaults covering file allocation modes (none vs. falloc), directory hygiene, concurrency tuning, disk space monitoring, and error recovery for long-running downloads.
  • Identified the root cause of HTTP 403 (errorCode=22) errors during large Hugging Face downloads as expiring signed URLs and per-connection rate limiting, with a prescriptive mitigation using reduced concurrency and extended retry delays.

10. Conclusions and recommendations

aria2 reliably saturates available bandwidth for large LLM downloads on Jetson AGX Orin and handles interruptions gracefully, provided three practices are consistently followed: always pass -c for large files; use a stable output directory so .aria2 control files remain co-located with their data files; and set --max-tries=0 so aria2 recovers from transient failures without manual intervention.

For daily workflows, standardize on one or two shell aliases (aria2fast, hfaria) and always invoke aria2 from the same directory paths. Always specify -o with an explicit filename when downloading from Hugging Face, as the platform's object storage backend assigns opaque hash-like keys that aria2 will use as the filename in the absence of an explicit override. This eliminates the most common source of filename confusion and simplifies subsequent resume operations.

When troubleshooting stubborn failures, apply interventions in order: reduce concurrency first, then increase retry delay, then inspect disk and filesystem health with dmesg and journalctl. Delete a partial file and its .aria2 sidecar only as a last resort, and only for the specific file that is failing — not for the entire batch. If a transient Hugging Face backend outage is causing persistent 403 errors near completion, the most effective response is to wait and retry rather than to restart a near-complete multi-gigabyte download from scratch.

Top comments (0)