Enterprise-grade security proxy that protects your package registries (npm, PyPI, Maven, Cargo, RubyGems, OpenVSX, NuGet, Go) by scanning packages with Socket's security API in real-time to block malicious packages before they reach your systems.
- npm (JavaScript/Node.js) -
registry.npmjs.org - PyPI (Python) -
pypi.org - Maven (Java) -
repo1.maven.org - Cargo (Rust) -
crates.io - RubyGems (Ruby) -
rubygems.org - OpenVSX (VS Code Extensions) -
open-vsx.org - NuGet (.NET) -
nuget.org - Go (Go Modules) -
proxy.golang.org - Conda (Python/R/etc.) -
conda.anaconda.org(treated as PyPI until native support)
✅ Real-time Security - Blocks malicious packages before installation
✅ Multi-Registry - Protects all 8 major package ecosystems
✅ Flexible Routing - Domain-based or path-based routing
✅ Auto-Discovery - Sync routes from Artifactory/Nexus automatically
✅ High Performance - Intelligent caching with Redis support
✅ Enterprise Ready - Outbound proxy, custom CAs, Splunk logging
✅ Zero Config - Works with public registries out-of-the-box
Socket Registry Firewall can be deployed in two ways:
- Pre-built Docker Image (Recommended) - Pull and run the official image
- Tarball Installation - Build your own image using the firewall tarball (for air-gapped or custom environments)
- Sign up at Socket.dev
- Go to Settings → API Keys
- Create API key with scopes:
packages,entitlements:list
# Create .env file with your Socket API token
cat > .env <<EOF
SOCKET_SECURITY_API_TOKEN=your-api-key-here
EOFOr export it in your shell:
export SOCKET_SECURITY_API_TOKEN=your-api-key-hereCreate a docker-compose.yml:
services:
socket-firewall:
image: socketdev/socket-registry-firewall:latest
ports:
- "8080:8080" # HTTP (redirects to HTTPS)
- "8443:8443" # HTTPS
environment:
# Required: Socket.dev API token
- SOCKET_SECURITY_API_TOKEN=${SOCKET_SECURITY_API_TOKEN}
volumes:
# Configuration file
- ./socket.yml:/app/socket.yml:ro
# SSL certificates directory
- ./ssl:/etc/nginx/ssl
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-fk", "https://localhost:8443/health"]
interval: 30s
timeout: 10s
retries: 3Create a minimal socket.yml:
# Minimal configuration - uses defaults for all public registries
# Access registries at: https://localhost:8443/npm/, /pypi/, /maven/, etc.
socket:
api_url: https://api.socket.dev
# Set internal container ports the firewall will bind to
ports:
http: 8080
https: 8443
path_routing:
enabled: true
domain: sfw.your_company.com
routes:
- path: /npm
upstream: https://registry.npmjs.org
registry: npm
# Optional: Customize performance settings
nginx:
worker_processes: 2
worker_connections: 4096sudo sh -c 'printf "127.0.0.1 sfw.your_company.com\n::1 sfw.your_company.com\n" >> /etc/hosts'
docker pull socketdev/socket-registry-firewall
docker compose up -dThat's it! The firewall is now protecting the npm registry at http://sfw.your_company.com:8080/npm/.
For air-gapped environments, custom base images, or when you need to build your own container, Socket provides the firewall as a tarball that can be extracted into any OpenResty-based image.
- Air-gapped environments - No access to Docker Hub
- Custom base images - Need specific OpenResty version or OS distribution
- Security requirements - Must build from source in your own registry
- Custom modifications - Need to add additional tools or configurations
- Obtain the tarball from Socket (e.g.,
socket-firewall-1.1.94.arm64.tgz) - OpenResty base image - Compatible with
openresty/openresty:1.27.1.2-11-alpineor similar
Create a Dockerfile in your project directory:
FROM openresty/openresty:1.27.1.2-11-alpine
# Copy and extract the Socket Firewall tarball
COPY socket-firewall-1.1.94.arm64.tgz /app/install/socket-firewall-1.1.94.arm64.tgz
COPY entrypoint.sh /app/entrypoint.sh
RUN chmod +x /app/entrypoint.sh \
&& tar -xzf /app/install/socket-firewall-1.1.94.arm64.tgz -C /
# Install basic dependencies
RUN apk add --no-cache curl ca-certificates git openssl bash && \
# Prefer IPv4 over IPv6 to avoid upstream IPv6 connection attempts
printf 'precedence ::ffff:0:0/96 100\n' >> /etc/gai.conf || true
# Install lua-resty libraries
RUN cd /tmp && \
# Install lua-resty-http
git clone https://github.com/ledgetech/lua-resty-http.git && \
cd lua-resty-http && \
cp -r lib/resty/* /usr/local/openresty/lualib/resty/ && \
cd /tmp && \
# Install lua-resty-openssl (needed for HTTPS)
git clone https://github.com/fffonion/lua-resty-openssl.git && \
cd lua-resty-openssl && \
cp -r lib/resty/* /usr/local/openresty/lualib/resty/ && \
cd /tmp && \
# Install lua-resty-redis (needed for Redis caching)
git clone https://github.com/openresty/lua-resty-redis.git && \
cd lua-resty-redis && \
cp lib/resty/redis.lua /usr/local/openresty/lualib/resty/ && \
cd / && \
rm -rf /tmp/lua-resty-http /tmp/lua-resty-openssl /tmp/lua-resty-redis
WORKDIR /app
ENTRYPOINT ["/app/entrypoint.sh"]Note: Adjust the tarball filename to match your version and architecture (e.g., socket-firewall-1.1.94.amd64.tgz for x86_64).
Download the entrypoint.sh script from Socket (provided with the tarball package) or request it from Socket support.
Place it in your project directory and make it executable:
chmod +x entrypoint.shThe entrypoint script handles:
- Configuration generation using
socket-proxy-config-tool - Environment variable loading
- Nginx configuration validation
- Auto-discovery daemon startup (if configured)
- Nginx process management
Create a docker-compose.yml for the tarball-based installation:
services:
socket-firewall:
build:
context: .
dockerfile: Dockerfile
image: socketdev/socket-registry-firewall-tar:latest
ports:
- "8085:8080" # HTTP (redirects to HTTPS)
- "8445:8443" # HTTPS
environment:
# Required: Socket.dev API token
- SOCKET_SECURITY_API_TOKEN=${SOCKET_SECURITY_API_TOKEN}
volumes:
# Configuration file
- ./socket.yml:/app/socket.yml:ro
# SSL certificates directory
- ./ssl:/etc/nginx/ssl
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-fk", "https://localhost:8443/health"]
interval: 30s
timeout: 10s
retries: 1Note: Different ports (8085/8445) are used in this example to avoid conflicts if running both methods simultaneously.
# Build the image
docker compose build
# Start the firewall
docker compose up -d
# View logs
docker compose logs -f socket-firewallThe Socket Firewall tarball includes:
/usr/local/bin/socket-proxy-config-tool- Configuration generation tool/usr/local/openresty/lualib/socket/*.lua- Lua modules for package parsing and security checks/usr/local/openresty/nginx/conf/snippets/- Nginx configuration snippets- Supporting files for all 8 ecosystems (npm, PyPI, Maven, Cargo, RubyGems, OpenVSX, NuGet, Go)
The tarball extracts to standard OpenResty paths, making it compatible with any OpenResty-based image.
When using tarball installation, you can:
- Use different base images: Change the
FROMline to use specific OpenResty versions or distributions - Add custom tools: Install additional packages in the RUN command
- Modify entrypoint: Customize the entrypoint script for your environment
- Layer scanning: Add image scanning tools in your build pipeline
- Internal registries: Push built images to your private container registry
After starting the firewall, verify it's working:
# Check health endpoint
curl -k https://localhost:8445/health
# Expected response:
{"status":"healthy","version":"1.1.94"}
# View startup logs
docker compose logs socket-firewall | grep -i "socket firewall"Both the pre-built image and tarball installation use the same socket.yml configuration file format.
Test npm:
# Configure npm to use the firewall
npm config set registry http://sfw.your_company.com:8080/npm/
npm config set strict-ssl false # Only for self-signed certs
# Install a package
npm install lodash --loglevel verbose
# Try to install a malicious package and watch Socket Firewall block the package.
npm install lodahs- Add more ecosystems into the
socket.yml, then test with these common language samples below.
Test pip:
# Configure pip to use the firewall
pip config set global.index-url https://localhost:8443/pypi/simple
pip config set global.trusted-host "localhost"
# Install a package
pip install requestsTest Maven:
# Add to ~/.m2/settings.xml
cat > ~/.m2/settings.xml <<'EOF'
<settings>
<mirrors>
<mirror>
<id>socket-firewall</id>
<url>https://localhost:8443/maven</url>
<mirrorOf>*</mirrorOf>
</mirror>
</mirrors>
</settings>
EOF
# Build your project
mvn install -Dmaven.wagon.http.ssl.insecure=true -Dmaven.wagon.http.ssl.allowall=trueTest Gradle:
edit your settings.gradle:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS) // or FAIL_ON_PROJECT_REPOS
repositories {
maven { url "https://localhost:8443/maven" }
}
}Create socket.yml for custom domains:
registries:
npm:
domains:
- npm.company.com
pypi:
domains:
- pypi.company.com
maven:
domains:
- maven.company.comSingle domain with path prefixes:
path_routing:
enabled: true
domain: firewall.company.com
routes:
- path: /npm
upstream: https://registry.npmjs.org
registry: npm
- path: /pypi
upstream: https://pypi.org
registry: pypi
- path: /maven
upstream: https://repo1.maven.org/maven2
registry: mavenAutomatically sync repository routes:
path_routing:
enabled: true
domain: firewall.company.com
mode: nexus # or 'artifactory'
private_registry:
api_url: https://nexus.company.com
api_key: your-nexus-api-token
interval: 5m # Auto-sync every 5 minutes
# Optional filters
include_pattern: ".*"
exclude_pattern: "(tmp|test)-.*"Routes update automatically when you add/remove repositories - no manual configuration!
See docs/AUTO-DISCOVERY.md for details.
The firewall auto-generates self-signed certificates on first run. Trust them:
macOS:
sudo security add-trusted-cert -d -r trustRoot \
-k /Library/Keychains/System.keychain ssl/fullchain.pemLinux:
sudo cp ssl/fullchain.pem /usr/local/share/ca-certificates/socket-firewall.crt
sudo update-ca-certificatesPlace your certificates in the ssl/ directory:
cp /path/to/cert.pem ssl/fullchain.pem
cp /path/to/key.pem ssl/privkey.pemmkdir -p ssl
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout ssl/privkey.pem \
-out ssl/fullchain.pem \
-subj "/CN=*.company.com" \
-addext "subjectAltName=DNS:firewall.company.com,DNS:npm.company.com,DNS:pypi.company.com"Route all upstream traffic through a corporate proxy:
socket:
outbound_proxy: http://proxy.company.com:3128
no_proxy: localhost,127.0.0.1,internal.company.comsocket:
outbound_proxy: http://proxy.company.com:3128
# Verify SSL with corporate CA
api_ssl_verify: true
api_ssl_ca_cert: /path/to/corporate-ca.crt
# Apply same CA to upstream registries
# (or set upstream_ssl_verify separately if different)For distributed deployments:
redis:
enabled: true
host: redis.company.com
port: 6379
password: your-redis-password
ttl: 86400 # 24 hours# Match worker_processes to CPU cores
worker_processes: 4
worker_connections: 8192
proxy:
connect_timeout: 60
send_timeout: 60
read_timeout: 60socket:
fail_open: true # Allow packages if Socket API is down (default)
# fail_open: false # Block all packages if Socket API is downOverride configuration via environment variables:
# Core settings
SOCKET_SECURITY_API_TOKEN=your-api-key # Required
SOCKET_API_URL=https://api.socket.dev # Default
SOCKET_CACHE_TTL=600 # Seconds, default: 600
SOCKET_FAIL_OPEN=true # Allow on API error
# Ports
HTTP_PORT=8080 # Default: 8080
HTTPS_PORT=8443 # Default: 8443
# Redis (optional)
REDIS_ENABLED=true
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=secret
# Proxy (optional)
SOCKET_OUTBOUND_PROXY=http://proxy:3128
SOCKET_NO_PROXY=localhost,127.0.0.1# Health endpoint (no auth required)
curl https://localhost:8443/health
# Expected response:
# {"status":"healthy","version":"1.1.23"}# All logs
docker compose logs -f socket-firewall
# Errors only
docker compose logs socket-firewall | grep -i error
# Security events
docker compose logs socket-firewall | grep -i blockForward security events to Splunk:
splunk:
enabled: true
hec_url: https://splunk.company.com:8088/services/collector/event
hec_token: your-splunk-hec-token
index: security
source: socket-firewallSee docs/SPLUNK.md for details.
# Check logs
docker compose logs socket-firewall
# Verify environment variables
docker compose exec socket-firewall env | grep SOCKET
# Test config generation
docker compose exec socket-firewall socket-proxy-config-tool generate --config /app/socket.yml# Check if package is blocked
docker compose logs socket-firewall | grep -i block
# Verify firewall is reachable
curl -I https://localhost:8443/health
# Test upstream connectivity from container
docker compose exec socket-firewall curl -I https://registry.npmjs.org# For testing, bypass SSL verification:
# npm
npm config set strict-ssl false
# pip
PIP_TRUSTED_HOST='localhost' pip install package
# Maven (add flags)
mvn install -Dmaven.wagon.http.ssl.insecure=true -Dmaven.wagon.http.ssl.allowall=true
# For production, trust the CA certificate (see SSL/TLS section above)# Verify API token is set
docker compose exec socket-firewall env | grep SOCKET_SECURITY_API_TOKEN
# Check API connectivity (from container)
docker compose exec socket-firewall curl https://api.socket.dev/v0/health
# Review fail_open setting
cat socket.yml | grep fail_openRemove blocked/warned packages from registry metadata responses:
metadata_filtering:
enabled: true
filter_blocked: true # Remove blocked packages
filter_warn: false # Keep warned packages (show warnings only)Pre-cache security status for faster lookups:
bulk_purl_lookup:
enabled: true
batch_size: 5000 # PURLs per batchFor 50+ routes, use external file:
path_routing:
enabled: true
domain: firewall.company.com
routes_file: /config/routes.ymlSee docs/EXTERNAL-ROUTES.md for format.
Client (npm/pip/mvn)
↓
Socket Firewall (this)
↓
Socket.dev API (security check)
↓
Upstream Registry (npmjs.org, pypi.org, etc.)
Request Flow:
- Client requests package from firewall
- Firewall extracts package name/version
- Firewall checks Socket API for security issues
- If safe: proxy to upstream and return package
- If malicious: return 403 Forbidden with reason
- Getting Started: This file
- Auto-Discovery: docs/AUTO-DISCOVERY.md
- External Routes: docs/EXTERNAL-ROUTES.md
- Redis Caching: docs/REDIS.md
- Splunk Integration: docs/SPLUNK.md
- Artifactory Auth: docs/ARTIFACTORY-AUTH.md
# Minimal config - no custom domains needed
# Just start with docker compose up -d
# Access at https://localhost:8443/npm/, /pypi/, /maven/, etc.registries:
npm:
domains: [npm.company.com]
pypi:
domains: [pypi.company.com]
maven:
domains: [maven.company.com]
cargo:
domains: [cargo.company.com]
rubygems:
domains: [rubygems.company.com]
openvsx:
domains: [vsx.company.com]
nuget:
domains: [nuget.company.com]
go:
domains: [go.company.com]path_routing:
enabled: true
domain: packages.company.com
routes:
- { path: /npm, upstream: https://registry.npmjs.org, registry: npm }
- { path: /pypi, upstream: https://pypi.org, registry: pypi }
- { path: /maven, upstream: https://repo1.maven.org/maven2, registry: maven }
- { path: /cargo, upstream: https://index.crates.io, registry: cargo }
- { path: /rubygems, upstream: https://rubygems.org, registry: rubygems }
- { path: /openvsx, upstream: https://open-vsx.org, registry: openvsx }
- { path: /nuget, upstream: https://api.nuget.org, registry: nuget }
- { path: /go, upstream: https://proxy.golang.org, registry: go }path_routing:
enabled: true
domain: firewall.company.com
mode: artifactory # or 'nexus'
private_registry:
api_url: https://artifactory.company.com/artifactory
api_key: your-artifactory-api-key
interval: 5m
default_registry: maven # Fallback for unknown repos- GitHub Issues: https://github.com/SocketDev/socket-nginx-firewall/issues
- Email: support@socket.dev
- Documentation: https://docs.socket.dev
- Socket Dashboard: https://socket.dev/dashboard
Proprietary - Socket Security Inc.
Need help? Check docs/ for detailed guides or contact support@socket.dev