Skip to content

Standalone Binary

Shield runs as a standalone binary -- no OpenParallax installation required. It exposes a gRPC and REST API for action evaluation and can serve as an MCP security proxy.

Installation

Linux / macOS

bash
curl -sSL https://get.openparallax.dev/shield | sh

This installs the openparallax-shield binary to /usr/local/bin/. Supports --version v0.1.0 for pinning and --dir /custom/path for custom install location.

From Source

bash
git clone https://github.com/openparallax/openparallax.git
cd openparallax
make build-shield
# Binary at: dist/openparallax-shield

Configuration

A default.yaml policy ships alongside the binary in the release archive. Shield uses it automatically when no custom policy is specified, so basic usage requires zero policy configuration.

The policy file can live anywhere -- Shield resolves it from the policy.file path in shield.yaml. By default it looks for default.yaml in the same directory as the binary. To customize:

  1. Copy default.yaml to a new file (e.g. my-policy.yaml)
  2. Edit the deny/verify/allow rules to match your environment
  3. Point shield.yaml at it: policy.file: my-policy.yaml

Three presets are available in the OpenParallax repository:

  • default.yaml -- balanced security (blocks sensitive paths, evaluates shell/external comms at Tier 2, allows workspace reads)
  • permissive.yaml -- relaxed rules for development environments
  • strict.yaml -- locks down all writes and external communication to Tier 2+

See Policy Syntax for the full rule format and pattern matching reference.

Create a shield.yaml file:

yaml
# Shield standalone configuration

# Server settings
listen: localhost:9090
grpc_listen: localhost:9091

# Policy (defaults to default.yaml next to the binary if omitted)
policy:
  file: default.yaml

# Classifier
classifier:
  model_dir: ~/.openparallax/models/prompt-injection/
  threshold: 0.85

# Heuristic engine
heuristic:
  enabled: true

# Tier 2 LLM evaluator
evaluator:
  provider: anthropic
  model: claude-sonnet-4-6
  api_key_env: ANTHROPIC_API_KEY

# Security
canary_token: SHIELD-CANARY-a8f3e9b2c4d5e6f7
fail_closed: true

# Rate limiting
rate_limit: 60        # evaluations per minute
daily_budget: 100     # Tier 2 evaluations per day
verdict_ttl: 300      # verdict cache TTL in seconds

# Audit logging
audit:
  enabled: true
  file: shield-audit.jsonl

# Logging
log_level: info
log_file: shield.log

Configuration Reference

FieldTypeDefaultDescription
listenstringlocalhost:9090REST API listen address
grpc_listenstringlocalhost:9091gRPC API listen address
policy.filestringdefault.yamlPath to YAML policy file (bundled default used if omitted)
classifier.model_dirstring~/.openparallax/models/prompt-injection/ONNX model directory
classifier.thresholdfloat0.85INJECTION confidence threshold
heuristic.enabledbooltrueEnable heuristic pattern matching
evaluator.providerstring--LLM provider for Tier 2
evaluator.modelstring--LLM model for Tier 2
evaluator.api_key_envstring--Env var for the API key
evaluator.base_urlstring--Custom base URL
canary_tokenstringauto-generatedToken for evaluator injection detection
fail_closedbooltrueBlock on errors
rate_limitint60Evaluations per minute
daily_budgetint100Tier 2 evaluations per day
verdict_ttlint300Verdict cache TTL (seconds)
audit.enabledboolfalseEnable audit logging
audit.filestringshield-audit.jsonlAudit log file path
log_levelstringinfoLog level: debug, info, warn, error
log_filestring--Log file path (stdout if omitted)

Commands

serve

Start the Shield server:

bash
openparallax-shield serve
openparallax-shield serve --config shield.yaml
openparallax-shield serve --config shield.yaml --port 8080

evaluate

Evaluate a single action from the command line:

bash
openparallax-shield evaluate \
  --action-type read_file \
  --payload '{"path": "/home/user/.ssh/id_rsa"}' \
  --config shield.yaml

status

Show Shield status:

bash
openparallax-shield status --config shield.yaml

mcp-proxy

Start Shield as an MCP security proxy:

bash
openparallax-shield mcp-proxy --config shield.yaml

See MCP Gateway for full documentation.

REST API

POST /evaluate

Evaluate an action.

Request:

json
{
  "action_type": "execute_command",
  "payload": {
    "command": "rm -rf /"
  },
  "min_tier": 0
}

Response:

json
{
  "decision": "BLOCK",
  "tier": 1,
  "confidence": 0.95,
  "reasoning": "heuristic [rm_rf_root, critical]: Recursive root delete detected",
  "action_hash": "sha256:a1b2c3d4e5f6...",
  "evaluated_at": "2026-04-03T10:30:00Z",
  "expires_at": "2026-04-03T10:35:00Z"
}

GET /health

Health check.

Response:

json
{
  "status": "ok",
  "tier0": true,
  "tier1_onnx": true,
  "tier1_heuristic": true,
  "tier2": true
}

GET /status

Shield status including budget usage.

Response:

json
{
  "active": true,
  "tier2_enabled": true,
  "tier2_used": 42,
  "tier2_budget": 100
}

Running as a Service

systemd (Linux)

Create /etc/systemd/system/openparallax-shield.service:

ini
[Unit]
Description=OpenParallax Shield - AI Security Pipeline
After=network.target

[Service]
Type=simple
User=shield
Group=shield
WorkingDirectory=/opt/shield
ExecStart=/usr/local/bin/openparallax-shield serve --config /opt/shield/shield.yaml
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal

# Security hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=/opt/shield/logs /opt/shield/audit
PrivateTmp=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true

# Resource limits
LimitNOFILE=65536
MemoryMax=2G

# Environment
Environment=ANTHROPIC_API_KEY=
EnvironmentFile=-/opt/shield/.env

[Install]
WantedBy=multi-user.target

Enable and start:

bash
sudo systemctl daemon-reload
sudo systemctl enable openparallax-shield
sudo systemctl start openparallax-shield
sudo systemctl status openparallax-shield

launchd (macOS)

Create ~/Library/LaunchAgents/dev.openparallax.shield.plist:

xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>dev.openparallax.shield</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/bin/openparallax-shield</string>
        <string>serve</string>
        <string>--config</string>
        <string>/opt/shield/shield.yaml</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
    <key>StandardOutPath</key>
    <string>/opt/shield/logs/shield.log</string>
    <key>StandardErrorPath</key>
    <string>/opt/shield/logs/shield-error.log</string>
    <key>EnvironmentVariables</key>
    <dict>
        <key>ANTHROPIC_API_KEY</key>
        <string></string>
    </dict>
</dict>
</plist>

Load and start:

bash
launchctl load ~/Library/LaunchAgents/dev.openparallax.shield.plist

Windows Service

Use sc.exe to register Shield as a Windows service, or use NSSM (Non-Sucking Service Manager) for more control over logging and restart behavior.

Using sc.exe:

powershell
sc.exe create OpenParallaxShield `
  binPath= "C:\Program Files\OpenParallax\openparallax-shield.exe serve --config C:\shield\shield.yaml" `
  start= auto `
  DisplayName= "OpenParallax Shield"

sc.exe start OpenParallaxShield

Using NSSM (recommended for production):

powershell
# Install NSSM (via Scoop or download from nssm.cc)
scoop install nssm

# Register the service
nssm install OpenParallaxShield "C:\Program Files\OpenParallax\openparallax-shield.exe"
nssm set OpenParallaxShield AppParameters "serve --config C:\shield\shield.yaml"
nssm set OpenParallaxShield AppDirectory "C:\shield"
nssm set OpenParallaxShield AppStdout "C:\shield\logs\shield.log"
nssm set OpenParallaxShield AppStderr "C:\shield\logs\shield-error.log"
nssm set OpenParallaxShield AppEnvironmentExtra "ANTHROPIC_API_KEY=sk-ant-..."

# Start the service
nssm start OpenParallaxShield

NSSM provides automatic restart on crash, log rotation, and a GUI for editing service parameters (nssm edit OpenParallaxShield).

Docker Deployment

Dockerfile

dockerfile
FROM golang:1.25-alpine AS builder
WORKDIR /src
COPY . .
RUN CGO_ENABLED=0 make build-shield

FROM alpine:3.20
RUN apk add --no-cache ca-certificates
COPY --from=builder /src/dist/openparallax-shield /usr/local/bin/
COPY security/shield/ /opt/shield/security/shield/
COPY prompts/ /opt/shield/prompts/

WORKDIR /opt/shield
EXPOSE 9090 9091

ENTRYPOINT ["openparallax-shield"]
CMD ["serve", "--config", "/opt/shield/shield.yaml"]

Docker Compose

yaml
version: '3.8'

services:
  shield:
    build: .
    ports:
      - "9090:9090"
      - "9091:9091"
    volumes:
      - ./shield.yaml:/opt/shield/shield.yaml:ro
      - ./security/shield:/opt/shield/security/shield:ro
      - ./prompts:/opt/shield/prompts:ro
      - shield-models:/root/.openparallax/models
      - shield-audit:/opt/shield/audit
    environment:
      - ANTHROPIC_API_KEY
    restart: unless-stopped
    deploy:
      resources:
        limits:
          memory: 2G
          cpus: '2'

volumes:
  shield-models:
  shield-audit:

Monitoring

Prometheus Metrics

Shield exposes metrics at /metrics when running as a standalone server:

# Evaluation counts by tier and decision
shield_evaluations_total{tier="0", decision="BLOCK"} 42
shield_evaluations_total{tier="0", decision="ALLOW"} 1337
shield_evaluations_total{tier="1", decision="BLOCK"} 5
shield_evaluations_total{tier="2", decision="ALLOW"} 28

# Evaluation latency
shield_evaluation_duration_seconds{tier="0"} 0.0001
shield_evaluation_duration_seconds{tier="1"} 0.052
shield_evaluation_duration_seconds{tier="2"} 1.2

# Budget usage
shield_tier2_budget_used 42
shield_tier2_budget_total 100

# Classifier status
shield_classifier_available{type="onnx"} 1
shield_classifier_available{type="heuristic"} 1

Health Checks

The /health endpoint returns HTTP 200 when Shield is operational. Use it for load balancer health checks, Kubernetes liveness probes, and Docker health checks:

yaml
# Docker Compose
healthcheck:
  test: ["CMD", "wget", "-q", "--spider", "http://localhost:9090/health"]
  interval: 10s
  timeout: 5s
  retries: 3
yaml
# Kubernetes
livenessProbe:
  httpGet:
    path: /health
    port: 9090
  initialDelaySeconds: 10
  periodSeconds: 10

Next Steps