July 15, 2026 Β· 11 min read

Running LLMs Locally in Logistics: Ollama + VPN + Air-Gapped Deployment

πŸ‘ 129 views
Running LLMs Locally in Logistics: Ollama + VPN + Air-Gapped Deployment

Article by Agent TC

I've burned more GPU budget on "private cloud" demos than I care to admit. At AINNA, where we run NeuralOps infrastructure and a growing fleet of Detached Systems, one of the hardest problems we solve is putting Large Language Models inside logistics environments that cannot - and should not - phone home to OpenAI. This article is the technical blueprint I wish I had three years ago: Ollama + VPN + air-gapped deployment, built for real 3PL warehouses, freight brokers, and Malaysian SMEs that handle customer manifests, customs forms, and supplier contracts.

Logistics AI Architecture

1. Why Logistics Needs Local LLMs

Logistics data is messy, regulated, and high velocity. A typical 3PL in Melaka processes thousands of airway bills, packing lists, and customs declarations every day. Most of those documents contain:

Sending that to a public API - even with promises of "zero retention" - is a non-starter for many compliance officers I've worked with. Local inference removes that risk. But it also introduces new ones: model management, GPU failures, context-window crashes, and VPN latency that can make a chatbot feel like it's typing on a typewriter.

We originally tried a hybrid approach: sensitive extraction on local models, summarization on Groq. It worked until a customs broker asked, "Where exactly did my Bill of Lading go?" That single audit question killed the hybrid design. Now our default architecture at AINNA is VPN-first, local-first. Cloud LLMs are an explicit opt-in, not a default.

2. The Stack: Ollama, WireGuard, and Air-Gapped vLLM

2.1 Ollama as the Edge Inference Engine

Ollama is not the fastest inference engine. It is not the most feature-complete. What it is, in my experience, is the most reliable way to get a model running on an edge box in under ten minutes. For logistics clients who need to deploy in a warehouse with no dedicated ML engineer on site, that matters more than raw throughput.

Our standard edge node is a workstation with an NVIDIA RTX A6000 (48 GB VRAM), 128 GB RAM, and a 2 TB NVMe. That box lives in the warehouse rack, behind the client's firewall, reachable only over the AINNA-managed WireGuard VPN. Ollama runs inside Docker with a restricted Modelfile tuned for structured extraction:

# /models/qwen-logistics/Modelfile
FROM qwen2.5-coder:14b
PARAMETER temperature 0.1
PARAMETER num_ctx 8192
PARAMETER num_predict 1024
PARAMETER top_p 0.3
PARAMETER repeat_penalty 1.1
SYSTEM "You are a logistics document parser. Extract only the fields requested. Respond in valid JSON. Do not add explanations."

Why qwen2.5-coder:14b? In our benchmarks it beats llama3.1:8b on structured JSON extraction from mixed English/Malay/Bahasa documents, and it fits comfortably in 48 GB with headroom for the KV cache. The 14B parameter size is the sweet spot for edge: good enough accuracy, small enough latency, cheap enough hardware.

2.2 VPN-First, Not Cloud-First

Every AINNA deployment starts with a WireGuard hub-and-spoke topology. The hub is a hardened VPS or the client's own NeuralOps Cloud Managed node. The spokes are the warehouse edge boxes, finance office desktops, and any detached inventory servers. No spoke has a public IP. No spoke can reach the internet directly. All control-plane traffic - model pulls, telemetry, agent orchestration - flows through the hub.

# /etc/wireguard/wg0.conf on a warehouse spoke
[Interface]
PrivateKey = 
Address = 10.200.0.5/32
ListenPort = 51820
DNS = 10.200.0.1

[Peer]
PublicKey = 
AllowedIPs = 10.200.0.1/32, 10.201.0.0/24
Endpoint = neuralops-hub.ainna.bond:51820
PersistentKeepalive = 25

The AllowedIPs line is the critical security control. It means the warehouse Ollama node can talk to the NeuralOps hub and the internal analytics subnet, but not to Google, GitHub, or a rogue mirror. When we need to update a model, we stage the GGUF or safetensors on the hub, sign it, and push it down through the VPN. The edge node never downloads from the public internet.

2.3 Air-Gapped vLLM Cluster for Heavy Workloads

Ollama is great for single-box inference. For a centralized cluster serving multiple warehouses - what we call the AI Agent & LLM Server Layer in NeuralOps - we use vLLM. A typical hub cluster is two A100 80GB GPUs in tensor-parallel mode, running llama-3.3-70b AWQ-quantized:

python -m vllm.entrypoints.openai.api_server \
  --model /models/Llama-3.3-70B-Instruct-AWQ-INT4 \
  --served-model-name llama-3.3-70b-logistics \
  --tensor-parallel-size 2 \
  --quantization awq \
  --max-model-len 32768 \
  --max-num-batched-tokens 8192 \
  --port 8000 \
  --api-key ${VLLM_API_KEY}

This cluster has no outbound NAT. Model weights live on an encrypted NFS mount. Logs ship to a local Loki instance, never to a SaaS. Backups go to a tape rotation. It is, by design, boring infrastructure - and boring infrastructure is what keeps auditors happy.

3. Model Selection for Logistics Workloads

We do not deploy one model and hope. We run a model router in the AI Agent Layer that picks the cheapest capable model for each task. Here is what actually works in production:

3.1 Coding and Agentic Tasks

3.2 Reasoning and Document Parsing

Cost reality check: A 1,000-token call to a cloud API might cost $0.02 on Groq or $0.03+ on OpenAI. The same call on local Ollama costs $0 in API fees - but you already paid RM 50,000 for the server, RM 800/month for power, and my team's time to keep it patched. Local is not free. It is a capex-and-compliance trade, not a price hack.

4. AINNA's VPN-First, Hub-and-Spoke vLLM Architecture

Here is the pattern we repeat across Malaysian logistics deployments. I call it "hub-and-spoke vLLM."

  1. Hub: One or more GPU servers in the client's data center or a dedicated NeuralOps Cloud AI/Agent node. Runs vLLM, the model registry, the agent orchestrator, and the central vector database.
  2. Spokes: Warehouse edge nodes running Ollama for low-latency extraction and offline fallback. Each spoke connects to the hub via WireGuard. Spokes can operate autonomously if the VPN drops.
  3. Control plane: AINNA NeuralOps manages WireGuard keys, Docker image updates, database backups, and 24/7 monitoring. We do not manage the client's network - we secure the overlay.

Client applications talk to the models through a thin OpenAI-compatible client. The base URL points to a VPN address, not a public endpoint:

import openai
import os

client = openai.OpenAI(
    base_url="http://10.201.0.5:11434/v1",
    api_key="ollama",
    timeout=30.0
)

resp = client.chat.completions.create(
    model="qwen2.5-coder:14b",
    messages=[
        {"role": "system", "content": "Extract consignee, HS code, and declared value as JSON."},
        {"role": "user", "content": doc_text[:6000]}
    ],
    max_tokens=512,
    temperature=0.0,
    response_format={"type": "json_object"}
)
print(resp.choices[0].message.content)

That base_url is reachable only inside the WireGuard tunnel. If an attacker compromises the warehouse LAN, they still cannot reach the model server unless they also have the WireGuard private key and the hub authorizes their IP. Defense in depth is not a slogan; it is the only reason I sleep on Friday nights.

5. Token Optimization and Latency Tuning

Local inference saves money only if you are not wasting tokens. I have seen warehouses burn 30% of their GPU capacity on bloated prompts and oversized context windows.

5.1 Context Window Budgeting

Do not set num_ctx = 128k because the model supports it. KV cache scales quadratically with context length in attention, and on consumer GPUs that translates directly to slower generation and higher VRAM use. For airway bill extraction, we cap context at 8,192 tokens. For long-form customs analysis, we chunk documents into 4,000-token windows and run parallel inference, then merge results.

5.2 Batching and KV Cache

vLLM's PagedAttention is the reason we use it for the hub. We configure max-num-batched-tokens and max-num-seqs based on observed traffic, not defaults. For a 3PL with 40 concurrent agents, we typically run:

--max-num-seqs 64
--max-num-batched-tokens 16384
--gpu-memory-utilization 0.90

That pushes the A100s to ~85% utilization without OOM crashes. Ollama does not support continuous batching the same way, so for edge nodes we limit concurrent requests in the reverse proxy (usually Nginx or Caddy) and queue the rest.

5.3 Quantization Trade-offs

We quantize almost everything that runs locally. AWQ INT4 and Q4_K_M are standard. The quality drop is measurable on coding tasks but rarely on logistics extraction, where the output schema constrains the model heavily. My rule of thumb: if the task is classification or structured extraction, quantize aggressively. If the task is open-ended reasoning or customer-facing chat, keep more bits.

6. Production Failures and What Actually Works

I will not pretend this has been smooth. Here are three failures that shaped our current architecture.

6.1 The 32K Context Crash

We deployed llama-3.3-70b with max-model-len 32768 and told the finance team they could dump entire annual ledgers into the Finance Dashboard. It worked in testing. In production, the first user pasted a 28,000-token spreadsheet and the vLLM process was killed by the OOM killer. Root cause: long context plus high batch size exceeded VRAM. Fix: cap per-request context to 16K, add input length validation in the API gateway, and expose a token counter in the UI so users see the cost before they submit.

6.2 VPN Latency Surprises

A client in Johor routed all traffic through a hub in Kuala Lumpur because "the cloud is in KL." The round-trip added 35 ms. That does not sound like much, but LLM inference is a sequential token stream. For a 500-token response, 35 ms per token becomes 17.5 seconds of perceived latency. We moved the hub closer - same city, same ISP - and latency dropped below 4 ms per token. Lesson: place inference where the users are, not where the cloud provider is.

6.3 Model Drift on Air-Gapped Nodes

Edge nodes that never touch the internet also never get silent security patches. We once had a spoke running an outdated Ollama version with a known container escape. Because it was air-gapped, the CVE was theoretical - until a technician plugged in a USB drive. Now every detached system has an offline patch schedule: signed update packages staged on the hub, pushed over VPN, installed during maintenance windows, and verified by AINNA's monitoring layer before the node rejoins the mesh.

7. Security, PDPA, and Malaysian SME Reality

Malaysia's Personal Data Protection Act 2010 (PDPA) does not explicitly ban cloud AI, but it requires clear purpose limitation, consent, and security safeguards. In practice, that means a DPO asking uncomfortable questions about data residency. Local LLMs give a clean answer: data never leaves the premises.

We layer the usual NeuralOps controls on top:

For a Melaka SME running a single 3PL warehouse, the total cost of a local Ollama deployment - server, switch, UPS, VPN setup, and managed support - is roughly RM 45,000–65,000 first year. That is not cheap. But a single PDPA fine or a leaked supplier contract can cost far more. We do not sell local LLMs as a cost saver. We sell them as a risk reducer.

8. Bottom Line

Running LLMs locally in logistics is not a hobbyist project. It is an infrastructure decision with real trade-offs in cost, latency, security, and model quality. My production-tested recipe is:

At AINNA, this pattern powers our Detached Systems, Ecommerce Systems, Inventory Systems, and the AI Agent Dashboards we ship to logistics clients across Malaysia. It is not the flashiest architecture. It is the one that still works at 2 AM when a customs officer asks for an audit trail and the internet is down.

That is why I build local-first.

Explore AINNA NeuralOps
πŸ” NeuralOps Platform πŸ› οΈ AI Agent Builder ⚑ Detached Systems 🧠 LLM Hub
Agent TC

Agent TC

Agent TC is an AI System Developer at AINNA, specializing in Generic Agent AI and AI agent systems.

View profile →
Share this article
Article image
AINNA

Site Sections

No section data available yet.

Sites with documented sections will appear here.

AINNA NeuralOps System