Hardened LLM Forge
Built with anycoder

Hardened Alpine Images for Qwen 3 & Gemma 3

Deploy modern LLMs in zero-trust Alpine containers with immutable, read-only layers, local-only execution, and the strictest kernel hardening stack available. Choose between Qwen 3 or Gemma 3 builds—both running entirely offline while exposing only loopback ports and maintaining a forensic-friendly footprint.

Base Distribution

Alpine 3.19

musl + BusyBox

Filesystem Mode

read-only

noexec / nosuid

Network Surface

127.0.0.1

loopback only

Capability Budget

1 retained

CAP_NET_BIND_SERVICE

Model Profiles

Qwen 3 Hardened

Qwen 3 (7B/14B)

Optimized for multilingual reasoning with quantized weights (q4_0, q8_0) stored on a read-only volume. Includes hardware entropy mirroring for deterministic offline runs.

  • Registry image: registry.local/qwen3-alpine:secure
  • ClamAV sweep of weights & binaries
  • Seccomp allowlist (45 syscalls)
  • Wireguard-ready for air-gapped updates
Gemma 3 Hardened

Gemma 3 (9B)

Latency-focused variant using llama.cpp runtime compiled with RELRO, stack canaries, and FORTIFY. Ships with detached attestations for every artifact.

  • Image: registry.local/gemma3-alpine:ro
  • Read-only overlayfs with tmpfs scratch
  • AppArmor profile usr.bin.gemma
  • Built for CPU-only, no CUDA dependency

Immutable Stack Blueprint

1. Minimal Alpine Layer

apk add --no-cache bash tini curl; remove compilers, docs, and locales; enable distroless-style runtime.

2. Model Injection (Read Only)

Weights unpacked to /opt/models, signed tarball verified with cosign, then mounted read-only through overlayfs.

3. Hardening Envelope

seccomp.json, AppArmor policy, drop capabilities, disable ptrace, use unprivileged user llm_runner (UID 1100).

4. Offline Runtime Contract

Entrypoint via tini, no DNS, /etc/resolv.conf emptied, firewall locks container to loopback, health checks executed locally.

Deployment Snippets (Copy & run)

FROM alpine:3.19

RUN addgroup -S llm && adduser -S llm -G llm \
 && apk add --no-cache tini ca-certificates \
 && apk add --no-cache --virtual .build-deps curl tar \
 && curl -sS https://registry.local/qwen3.tar.gz | tar xz -C /opt \
 && apk del .build-deps \
 && chown -R llm:llm /opt

USER llm
WORKDIR /opt/runtime
ENTRYPOINT ["/sbin/tini","--"]
CMD ["./launch.sh","--offline","--rofs"]
services:
  qwen3-hardened:
    image: registry.local/qwen3-alpine:secure
    read_only: true
    tmpfs:
      - /tmp:rw,noexec,nosuid,size=64m
      - /run:rw,noexec,nosuid,size=16m
    network_mode: "none"
    security_opt:
      - no-new-privileges:true
      - apparmor=usr.bin.qwen3
      - seccomp=/policies/seccomp.json
    cap_drop: ["ALL"]
    cap_add: ["NET_BIND_SERVICE"]
    command: ["./serve","--port","8080","--bind","127.0.0.1"]
docker run \
  --rm \
  --read-only \
  --tmpfs /tmp:rw,noexec,nosuid,size=64m \
  --tmpfs /var/log:rw,noexec,nosuid,size=16m \
  --cap-drop ALL \
  --cap-add NET_BIND_SERVICE \
  --security-opt seccomp=/policies/seccomp.json \
  --security-opt apparmor=usr.bin.gemma \
  --network none \
  -p 127.0.0.1:8080:8080 \
  registry.local/gemma3-alpine:ro \
  ./serve --offline --model /opt/models/gemma3.bin

Security Posture Matrix

Filesystem

Rootfs sealed read-only, tmpfs scratchpads with size quotas & noexec.

Network

Docker network none; optional unix socket for supervisor only.

Supply Chain

cosign attestations, SBOM exported via syft, images pinned by digest.

Runtime

Seccomp allowlist, AppArmor enforce, kernel keyring disabled.

Entropy

Optional rngd sidecar if hardware RNG unavailable (offline safe).

Observability

Logs to stdout/stderr only; can be piped to local filebeat agent.

Offline Controls

Internet Egress

Hard-blocked via iptables

Model FS Mutations

Overlay set as RO

Local-only Serving

127.0.0.1:8080