Stop Pulling Weights Live: Build a Private Model Registry Before the Next HF Incident

By Diogo Hudson Dias
DevOps engineer verifying signed AI model artifacts on a laptop in front of GPU server racks in a data center.

If you wouldn’t apt-get from a random mirror in production, why are your inference pods curling weights from the open internet at boot?

After the latest Hugging Face break-in was dissected in the news, it should be obvious: your model artifact pipeline is a supply chain. Treat it like one. Availability is reason enough—security seals the deal. Rate limits, deleted repos, or a tampered tokenizer can take down your agent platform just as surely as a database outage.

This is a CTO playbook for building a private, signed, policy-governed model registry. It’s not another academic ode to SLSA. It’s what to stand up in 90 days so your agents don’t fall over the next time a public model hub hiccups.

First, the ugly math: cold starts and egress are killing you

Let’s say you deploy a quantized 70B model for retrieval-augmented generation. Numbers you can bank on:

  • Base FP16 weights: ~140–160 GB. Quantized GGUF for production: 30–50 GB.
  • Tokenizer + vocab + merges + safetensors/gguf index + LoRA adapters: +1–3 GB.
  • Autoscaling from 0 to 10 replicas? First deploy pulls ~0.3–0.5 TB.
  • Cloud egress from object storage or cross-AZ traffic often runs $0.02–$0.09/GB. That’s $6–$45 per cold scale event—before you serve a single token.

More important: if your nodes pull directly from a public hub, you’ll hit per-IP rate limits, 429s, or timeouts. Add 10–20 minutes to warm each pod with 50 GB at 100–200 MB/s effective throughput under real-world contention. Those 10–20 minutes are SLO violations waiting to happen.

Threat model: what actually goes wrong

  • Swapped artifacts: A compromised repository serves a modified tokenizer.json that silently degrades or hijacks behavior. You won’t notice until your evals drift.
  • Pickle landmines: Legacy PyTorch checkpoints with pickled code paths can execute arbitrary code at load. If your loader “helpfully” supports it, you gave RCE to whoever controls the artifact.
  • Quantization toolchain drift: Tiny changes in k-quant or activation ordering can yield different perplexity and tool-use rates, even if the filename matches.
  • License sprawl: A “non-commercial” LoRA slides into production because someone copied a model_id from a notebook.
  • Availability collapse: A popular model gets yanked or renamed; pods stall on startup; your autoscaler churns.

These are not hypothetical. They are the same classes of failures you already learned to prevent for containers and OS packages—now repeated for model artifacts.

Decision framework: do you need a private registry?

You don’t need to be OpenAI to justify one. If any of these are true, you do:

  • You run production inference where cold-starts matter (SLOs on first-token latency or request per second).
  • You’re in regulated sectors (finance, healthcare, education) or serve minors. Auditability matters.
  • Your monthly egress on weights exceeds $500 or your team re-pulls artifacts multiple times per week.
  • You ship agents that call tools. The blast radius of a tampered checkpoint is not “just worse text.” It’s money movement or ticket updates.

When can you wait? Proof-of-concepts with a single toy model, no autoscaling, and no user data. Once you see the first 429 from a public hub during a deploy, you’re already late.

Architecture: a model registry that fits your stack

Transport: use the registry you already understand

  • OCI registry as the backbone: Harbor, Artifactory, or ECR/GCR/ACR. They support immutability, replication, RBAC, and Notary v2 signatures. You can store arbitrary artifacts via ORAS: push safetensors, GGUF, tokenizers, LoRAs as first-class blobs.
  • Object store mirror for bulk: Back the registry with S3/GCS/Azure Blob for cheap storage and multi-region replication. Keep the registry index small; offload big layers to object storage with signed URLs.

Format policy: ban pickle, standardize metadata

  • Allowed formats: safetensors for frameworks, GGUF for llama.cpp-class inference. Disallow any artifact that requires Python pickle to load.
  • Model SBOM: For each model version, embed a JSON manifest listing base weights hash, tokenizer hash, quantization tool version, LoRA parent hash, license, and intended-usage tags. Store this as an OCI artifact attached to the weight digest.

Signing and provenance: no signature, no run

  • Sign every artifact with Sigstore Cosign or Notary v2. Store public keys in your KMS or use keyless OIDC with your CI as the identity. Attach SLSA provenance (in-toto) describing how the artifact was built or transformed.
  • Binary Authorization at deploy: Admission controllers reject unsigned or untrusted-digest models. This is table stakes for containers; apply it to models.

Import pipeline: one way in, many ways out

  1. Importer service: A dedicated job with the only egress to public hubs. It pulls by immutable reference (commit SHA or tag digest), converts to approved formats in a hermetic container, computes digests, generates SBOM + attestation, and pushes to your registry.
  2. Policy gate: The importer enforces license allow-lists and format policy. If license = non-commercial and env = prod, reject. If format = pickle, reject.
  3. Quarantine staging: New imports land in a staging project. CI runs evals and security scans (e.g., scan tokenizer merges, vocab shifts, and config diffs). Promotion to prod is a deliberate action that re-signs under a prod key.

Runtime verification: fast and ruthless

  • InitContainers verify signatures and digests before weights touch the GPU. If verification fails, the pod never becomes ready.
  • Local NVMe cache with LRU: Keep hot weights on node-local SSDs and validate digests before use. This cuts warm-up by minutes and slashes east-west traffic.
  • Multi-region replication with pre-warming: Replicate artifacts to the target region’s registry and pre-warm caches during deploy windows.

Observability and audit

  • Artifact-level telemetry: Emit counters keyed by model_digest, tokenizer_digest. If perplexity or tool-use rates drift, you can prove you’re running the same bits.
  • Access logs: Every pull is attributable to a service account and environment. You’ll know which pod ran which digest at which time.

The developer experience: don’t make it painful

  • One command to import: Provide a CLI: modelctl import hf://org/model@sha -o my-registry/models -p staging. It prints the internal URI and attestation IDs.
  • Deterministic promotion: modelctl promote models/llama-3-70b@sha -e prod. Same digest, new signature, visible to prod namespaces.
  • Self-serve catalog: A web UI listing approved models, hashes, licenses, and example code snippets for loaders across Python, Rust, Go.

Policy that bites: examples you can borrow

Use OPA/Gatekeeper or your platform’s admission controls. Translate principle to code:

Block unsigned or untrusted digests

Rule: Only allow models with a Cosign signature by org=ml-platform and with provenance type=model-importer@v1.

Outcome: A stray hard-coded HF URL in a deployment manifest fails admission.

Enforce license allow-list

Rule: If env=prod, license in [Apache-2.0, MIT, Meta-Llama, BigCode OpenRAIL].

Outcome: Non-commercial or research-only licenses never clear promotion to prod.

Disallow pickle-loading code paths

Rule: Loader images used in prod must pass a static scan proving no import of torch.load with unpickler enabled.

Outcome: Even if a dev tries to sneak in a convenience loader, it won’t deploy.

Cost and performance: yes, this saves money

  • Storage: 2 TB of weights on S3/GCS runs ~$46–$50/month at standard tiers. That’s less than a single day of production egress during a chaotic deploy.
  • Egress: Pulling from a regional registry inside your VPC/AZ is pennies. Eliminating repeated cross-region pulls easily saves $500–$2,000/month at modest scale.
  • Cold-starts: Pre-warmed NVMe caches cut 10–20 minutes of warm-up per replica to under 2 minutes, depending on I/O and checksum speed. That’s the difference between a graceful deploy and a PagerDuty weekend.

Rollout plan: 30/60/90 days

Days 1–30: Make it stop hurting

  • Stand up a managed or self-hosted OCI registry (Harbor/Artifactory/ECR) with immutability.
  • Build the importer job that fetches a single critical model, converts to safetensors/GGUF, and signs with Cosign (key in KMS).
  • Wire an initContainer to verify signatures and digests before model load. Roll this to your busiest service.
  • Block direct egress to public hubs from production namespaces; only the importer has access.

Days 31–60: Put policy in the loop

  • Add license allow-list and pickle ban to the importer. Fail imports that violate policy.
  • Create staging and production projects in the registry. Require promotion (and a second signature) to go prod-visible.
  • Attach an SBOM and provenance (in-toto/SLSA) to every artifact. Start logging pulls with service-account identity.
  • Introduce NVMe node-local caches with LRU and checksum-on-use.

Days 61–90: Make it boring

  • Replicate the registry to all production regions. Pre-warm caches during low-traffic windows.
  • Expose a CLI and internal catalog UI. Integrate with your model router and feature flags.
  • Set binary authorization on the cluster: no signature, no run. Add canaries that intentionally try to pull public URLs and alert if they succeed.
  • Run a game day: revoke a signer key, pull an artifact, attempt an unsigned deploy, and verify that everything fails closed.

What about fine-tunes and adapters?

Treat LoRAs and merged checkpoints exactly like base weights:

  • Adapters are code: They change behavior materially. Sign them. Track their parent digest. Enforce that adapters can only target approved parent digests.
  • Merged checkpoints get a new identity: Never tag a merged artifact with the base model’s ID. New digest, new SBOM, new evals.
  • Dataset artifacts: If you host training data deltas or synthetic corpora, store them as versioned artifacts with the same signing and policy gates. You’ll need this for reproducibility and audits.

Multi-cloud and edge: don’t strand your bytes

  • Vendor lock-in avoidance: OCI and ORAS mean you can mirror between ECR/GCR/ACR/Harbor. Keep the import pipeline declarative so you can recreate mirrors quickly elsewhere.
  • Edge/On-device: If you ship quantized models to mobile or IoT, front them with a private CDN, still backed by the registry as origin. Sign the payload and verify on device before first run.

Organizational reality: who owns this?

  • Platform/Infra owns the registry, signing keys, admission policies, and importer service.
  • ML Platform owns format policies, SBOM schema, eval gates, and model catalog.
  • Security owns key management policy, incident response, and game days.

If you’re short-staffed, a nearshore pod can build this in parallel with your core team. Expect 6–8 hours/day overlap, a 4–6 week first milestone for the importer and verification path, and another 4–6 weeks to harden policy and multi-region replication.

What about “managed model hubs” and vendors?

Great—use them as upstreams, not production dependencies. The rule is simple: One way in, many ways out. Your importer pulls from vendors, normalizes and signs the bytes, and your runtime consumes only what your platform has vouched for. If a vendor rotates a URL or a license overnight, your runtime shouldn’t even notice.

The skeptic’s corner: is this overkill?

You already do this for containers. Models are bigger, touchier, and higher blast-radius. The Hugging Face incident made headlines; the quieter reality is availability, cost, and drift. A private model registry turns “hope the internet is up” into “deploy is a local file copy.”

Key Takeaways

  • Public hubs are great upstreams, terrible production dependencies. Build a private, signed, policy-governed model registry.
  • Use an OCI registry plus ORAS for transport, safetensors/GGUF for formats, and Sigstore/Notary for signatures.
  • Enforce “no signature, no run” with admission controls; ban pickle; allow-list licenses; attach SBOM and provenance.
  • Importer service is the only egress to public hubs. It converts, signs, scans, and promotes artifacts across staging → prod.
  • Expect 10–20 minute warm-ups to drop to under 2 minutes with local caches; egress savings often exceed $500/month.
  • Roll out in 90 days: stand up the registry, add policy, replicate regions, and run game days to ensure it fails closed.

Ready to scale your engineering team?

Tell us about your project and we'll get back to you within 24 hours.

Start a conversation