MaruOpsInfrastructure and AI notes

About (Korean)Contact (Korean)

Download and Archive safetensors Models for an Offline Environment

USB flash drive in white and red case

Reference photo · USB flash drive in white and red case · Photo: Dmitry Makeev / Source / CC BY-SA 4.0 · Resized for listings; illustrative photo, not the tested environment

For an offline LLM environment, prepare the model directory, runtime packages and integrity records together. Download and archive the required files on a connected preparation server. On the internal server, verify the checksums and load the model from its local path.

This article explains the process of moving the safetensors model on Linux, using Hugging Face’s Qwen/Qwen2.5-0.5B-Instruct as an example. Unlike the existing Ollama model storage location/offline execution article, Transformers reads the model folder directly.

Model import structure at a glance

Prepare it from the Internet, move it to a file and run it internally.

01 · Internet section

Download and run confirmation

Model Weights · Settings · Tokenizer

Python package and version history

02 · Import file

Compression/Checksum Delivery

bundle/ → tar.gz

Compressed file + .sha256

03 · Dark site

Verify·Release·Execute

Verify checksum → Install local package

Local path + offline mode

Composition of bundle/ in compressed file

model/

Weights · Settings · Tokenizer

wheelhouse/

Python packages for offline installation

run_local.py

Executable code that reads the local model

requirements.lock · SHA256SUMS · records/

Package version · File checksum · Model history

The Python/OS environment for the internal server is prepared separately. The virtual environment folder is not copied.

On this page

Files to import and execution environment

.safetensors is a format that stores the model’s weights. A typical Transformers text model requires weights, model structure settings, and a tokenizer that converts sentences into tokens. The sharded weights must get all the pieces pointed to by the index file. You can see this structure in the local model loading documentation for Transformers and Sharded checkpoint documentation.

File/DirectoryReason for bringing in
model.safetensors or all splits *.safetensorsactual model weights
config.jsonModel structure and setup
model.safetensors.index.jsonMaps weight tensors to files in a sharded model. A single-file model may not need this index.
Tokenizer/Chat Template FileConfiguration by model such as tokenizer.json, tokenizer_config.json, vocabulary files, etc.
generation_config.json, README·LicenseCreation settings, model description and terms of use provided.
wheelhouse/, requirements.lock, executable codeInstall the Python package on the internal network and run it in the same way

The commands assume Bash, GNU tar and coreutils on Linux x86_64 with Python 3.11, venv and pip available. The model archive does not include Python or OS packages. Match the preparation and internal servers’ OS family, CPU architecture and Python version, and check RAM and working disk capacity. On Windows, the steps can run inside a WSL2 Linux environment.

The example uses a small text model and CPU execution to verify the fetch procedure. The Qwen model card lists the license for this repository as Apache-2.0. If you choose a different model, first check the model card and license from the relevant repository and whether the version of Transformers you are using is supported. Qwen2.5-0.5B-Instruct model card is the reference material.

Get packages and models online

Working folder and dedicated virtual environment

Create a new working folder on the staging server and proceed within it. The versions below are for reproduction of this article and do not necessarily mean that they are the most recent versions. The installation path of PyTorch for CPU follows PyTorch official version-specific installation instructions.

mkdir -p ~/darksite-llm/bundle/{model,wheelhouse,records}
cd ~/darksite-llm

python3.11 -m venv .prepare-venv
source .prepare-venv/bin/activate

python -m pip install "torch==2.8.0+cpu" \
  --index-url https://download.pytorch.org/whl/cpu
python -m pip install \
  "transformers==4.57.1" \
  "huggingface_hub==0.36.0" \
  "safetensors==0.6.2"
python -m pip check

If the installation fails, resolve the cause before moving on to downloading the model. Even if there is already an execution environment on the internal network, you must check whether the package version and model are supported for that environment. The virtual environment folder itself depends on the path and operating system, so it is not copied but recreated on the internal server.

Freeze commit and download model folder

Find the commit ID at the time of download and pass that value to --revision. It’s easier to keep track of which files were imported than just recording the branch name. If you omit the individual file name in hf download, you can receive the storage file together, and you can specify the folder for import in --local-dir. Refer to Hugging Face CLI document .

export MODEL_ID="Qwen/Qwen2.5-0.5B-Instruct"
export MODEL_DIR="$PWD/bundle/model"

MODEL_REVISION=$(python -c \
  'import os; from huggingface_hub import HfApi; print(HfApi().model_info(os.environ["MODEL_ID"]).sha)')
export MODEL_REVISION

hf download "$MODEL_ID" \
  --revision "$MODEL_REVISION" \
  --local-dir "$MODEL_DIR"

printf '%s\n' "$MODEL_ID" > bundle/records/model-id.txt
printf '%s\n' "$MODEL_REVISION" > bundle/records/model-revision.txt
date -u +%FT%TZ > bundle/records/downloaded-at-utc.txt
python -VV > bundle/records/python-version.txt
uname -m > bundle/records/architecture.txt
cat /etc/os-release > bundle/records/os-release.txt

The example public model does not require separate login. The access restriction model is received after executing hf auth login on the staging server with an account that agrees to the terms of use. Do not place the entire token store or user home in the import archive.

This example takes the entire repository to ensure no necessary configuration files are missed. If there are large files of various precisions and formats in different storage, check the list and model card first. Even when selecting files, the weights, settings, and tokenizers of the same commit are maintained as one set. The image generation model, multimodal model, and LoRA adapter require different components than this text model.

find bundle/model -maxdepth 2 -type f -printf '%P\n' | sort
find bundle/model -type l -print
du -sh bundle/model

In the file list, check config.json, the tokenizer file, and model.safetensors. If it’s a partitioned model, check the index and all the pieces. When the second command encounters a symbolic link, it stops compression and verifies that the actual file is inside the import folder. If you only copy the snapshot folder in the Hub cache, the files pointed to by the link may be missing. Hub Uses the local folder method described in Download/Cache Guide.

Create executable code that reads from a local path

Save the following contents as bundle/run_local.py. The model path is calculated based on the location of the executable file, so it will work even if you unzip it to a different directory. The example uses CPU and float32, and specifies that the weights should only be read from safetensors.

from pathlib import Path

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

model_dir = Path(__file__).resolve().parent / "model"

tokenizer = AutoTokenizer.from_pretrained(
    str(model_dir),
    local_files_only=True,
    trust_remote_code=False,
)
model = AutoModelForCausalLM.from_pretrained(
    str(model_dir),
    local_files_only=True,
    trust_remote_code=False,
    use_safetensors=True,
    dtype=torch.float32,
    attn_implementation="eager",
)
model.eval()

messages = [
    {"role": "user", "content": "Explain what an offline language model is in one sentence."}
]
text = tokenizer.apply_chat_template(
    messages,
    tokenize=False,
    add_generation_prompt=True,
)
inputs = tokenizer(text, return_tensors="pt")

with torch.inference_mode():
    output = model.generate(
        **inputs,
        max_new_tokens=48,
        do_sample=False,
        pad_token_id=tokenizer.eos_token_id,
    )

answer = output[0, inputs["input_ids"].shape[1]:]
print(tokenizer.decode(answer, skip_special_tokens=True))

local_files_only=True causes only the specified local files to be used. trust_remote_code=False is a setting that disallows custom Python code from the repository. This example model uses the structure implemented in Transformers. If other models require custom code, you should review that code and execution environment separately from adding the files.

On the staging server, set offline mode as shown below and run it once. HF_HUB_OFFLINE must be set before loading the library. The scope of application of this variable is Hugging Face Hub communication, not the function of blocking the network of the entire server. Please refer to the official environment variable description.

HF_HUB_OFFLINE=1 HF_HUB_DISABLE_TELEMETRY=1 \
  python bundle/run_local.py

When the response is printed, you have confirmed the model loading and short creation request. Make sure that you actually read bundle/model to be fetched, so as not to depend on other programs or existing caches that have entered the remote repository ID. The English questions are for reproduction purposes only, and the import procedure is the same even if you change them to Korean questions.

Binding wheel files for internal network installation

Even if you move the model folder, the installation stops when pip install transformers is connected to the Internet on the internal server. Record the package version in a dedicated virtual environment on the staging server and receive the corresponding version’s wheel file and dependencies. wheel is the distribution file for installing Python packages.

python -m pip freeze > bundle/requirements.lock
python -m pip download \
  --only-binary=:all: \
  --dest bundle/wheelhouse \
  --extra-index-url https://download.pytorch.org/whl/cpu \
  -r bundle/requirements.lock

python -m pip check
ls bundle/wheelhouse

--only-binary=:all: causes the source build to only receive wheels instead of the required files. If this step fails, verify that you have a wheel for your target, or have a deployment file built and verified in a compatible staging environment. Wheels from other OS or Python versions cannot be installed as is. pip download Official document outlines target platform options and restrictions.

Since this is a CPU example, CUDA·NVIDIA drivers are not included. When using it as a GPU, you must separately prepare a PyTorch build and additional kernel and quantization libraries appropriate for the target GPU and driver and test again. Just unzipping the model file does not install the GPU execution environment.

Creating and compressing checksums

Prepare the model file, wheel, and executable code and run them in the working folder. If you create separate checksums for the internal files and the checksum for the compressed file itself, you can check for damage during transmission and omissions after decompression. model/.cache metadata for download resumption is excluded from the bundle.

(
  cd bundle
  find . -type f \
    ! -path './model/.cache/*' \
    ! -path './SHA256SUMS' -print0 \
    | sort -z \
    | xargs -0 sha256sum > SHA256SUMS
  sha256sum -c SHA256SUMS
)

tar --exclude='bundle/model/.cache' \
  -czf qwen25-darksite-bundle.tar.gz bundle

sha256sum qwen25-darksite-bundle.tar.gz \
  > qwen25-darksite-bundle.tar.gz.sha256

du -sh bundle qwen25-darksite-bundle.tar.gz

If the output contains FAILED or the command fails, do not import and resolve the cause. Compression is used as a method for delivering multiple files and does not assume significant weight reduction. You need space to store the original and compressed files together in the preparation section, and space to store the compressed and unzipped files together in the internal section.

Move qwen25-darksite-bundle.tar.gz and qwen25-darksite-bundle.tar.gz.sha256 together to an approved medium or import channel. Since the checksum is a means of verifying identity, it also leaves the original hash in the trusted import record. Model usage conditions and the organization’s file inspection and import procedures also apply.

Verify and unzip on dark site

Assume that you imported two files as /data/import to your internal server. Replace the path with the actual location and prepare the extraction destination as a new directory that can be written by the execution account. If you don’t immediately overwrite the existing model, you can still use the old model if something goes wrong.

cd /data/import
sha256sum -c qwen25-darksite-bundle.tar.gz.sha256

tar -tzf qwen25-darksite-bundle.tar.gz

mkdir -p /data/llm/releases/qwen25-offline-01
tar --no-same-owner \
  -xzf qwen25-darksite-bundle.tar.gz \
  -C /data/llm/releases/qwen25-offline-01

cd /data/llm/releases/qwen25-offline-01/bundle
sha256sum -c SHA256SUMS

Make sure the first verification is OK and then proceed to the next command. Also check if the file with tar -tzf is under bundle/. If the final verification detects any omissions or inconsistencies, execution is stopped and the transfer copy and release path are checked.

Install and run without querying external storage

Run it from the extracted bundle directory. The internal server must also have Python 3.11 and venv·pip. Use --no-index and --find-links together to specify only the wheel directory imported as the installation target. This is the method shown in pip’s local package installation guide.

python3.11 -m venv .venv
source .venv/bin/activate

python -m pip install \
  --no-index \
  --find-links ./wheelhouse \
  -r requirements.lock

python -m pip check

HF_HUB_OFFLINE=1 HF_HUB_DISABLE_TELEMETRY=1 \
  python run_local.py

Check whether the answer comes with the same code in the preparation section and the internal section. If both installation and model execution pass in a test environment where external communication is blocked, it is easy to find parts that rely on existing Internet caches or remote downloads. If a separate web UI, RAG, or search tool is attached, the network dependency of that component is also checked separately.

When the file exists but does not run

symptomsWhat to check firstaction
config.json not foundFile structure in the passed pathPass the directory containing config.json instead of a single repository ID or safetensors file.
Tokenizer/Chat Template ErrorTokenizer files and model typesFetch the tokenizer from the same commit and check the dialog type of the model card
Weight piece not foundAll shards pointed to by the indexGet the missing pieces back from the same commit and rewrite the checksum
Hub connection attempt/offline file errorLocal path, offline variable setting timeSpecify variables before starting a process and check for missing required files
No matching distribution·wheel installation errorPython·OS·architecture·dependenciesReconfigure the wheel bundle on a staging server that is compatible with the target
Insufficient RAM/VRAMModel precision, context, concurrent requestsReduce run size or select appropriate model/memory configuration
Unsupported model/quantization errorRuntime version and quantization_configVerify supported versions and required packages in the preparation section and import them together.

Even if the file extension is the same, the required execution conditions are different for AWQ·GPTQ·FP8 models and LoRA adapters. If you only received the adapter, you must also have the base model. I do not assume that the CPU scripts in this article can be directly applied to other types of safetensors files.

For Ollama or llama.cpp, follow the model architecture and import procedures supported by the runtime. Changing the extension to .gguf does not convert the format. See the separate llama.cpp GGUF and CPU/GPU options guide.

Confirmed scope and official data

Official documents and implementation procedures confirmed as of October 22, 2026. I downloaded and compressed the example model from Python 3.11.17, PyTorch 2.8.0+cpu, and Transformers 4.57.1 ​​in a Debian 13 x86_64 container. In a separate container with the external network turned off, we verified the compressed file and internal file checksum, installed a new virtual environment using only the wheel, and generated pip check and a short answer. GPU execution and other OS/large models were not included in this verification.

When changing to a model to be used internally, download, run, and reinstall it first in the preparation section and import it as a new bundle. Keeping model commits, package lists, and checksums together allows you to revisit the same set of files in the future.