Downstream Deployment Guide

Deploy the Socket Registry Firewall between developers/CI and the package registry. Developers and CI systems point their package managers at the firewall instead of directly at the public or private registry.

Developer / CI  --->  Socket Firewall  --->  Public Registry (npmjs.org, pypi.org, etc.)
                                        --->  Private Registry (Artifactory / Nexus)

Prerequisites

  • Docker and Docker Compose
  • Socket.dev API key with scopes: packages:list, entitlements:list
  • DNS or /etc/hosts entry for the firewall domain (for path-based routing)

Step 1: Set Your API Token

export SOCKET_SECURITY_API_TOKEN=your-api-key-here

Or create a .env file:

cat > .env <<EOF
SOCKET_SECURITY_API_TOKEN=your-api-key-here
EOF

Step 2: Create Configuration

Create socket.yml with path-based routing (recommended for most setups):

Be sure to set the domain value to the domain you intend to host the firewall on.

socket:
  api_url: https://api.socket.dev

ports:
  http: 8080
  https: 8443

path_routing:
  enabled: true
  domain: sfw.your_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: /nuget
      upstream: https://api.nuget.org
      registry: nuget
    - path: /go
      upstream: https://proxy.golang.org
      registry: go
    - path: /vscode
      upstream: https://marketplace.visualstudio.com
      registry: vscode
    - path: /openvsx
      upstream: https://open-vsx.org
      registry: openvsx
    - path: /conda
      upstream: https://repo.anaconda.com/pkgs/main
      registry: conda

nginx:
  worker_processes: 2
  worker_connections: 4096

Include only the registries you need.

Alternative: Domain-Based Routing

If you prefer separate domains per registry:

registries:
  npm:
    domains: [npm.company.com]
  pypi:
    domains: [pypi.company.com]
  maven:
    domains: [maven.company.com]

Each domain needs a DNS record pointing to the firewall.

Step 3: Create Docker Compose File

services:
  socket-firewall:
    image: socketdev/socket-registry-firewall:latest
    ports:
      - "8080:8080"
      - "8443:8443"
    environment:
      - SOCKET_SECURITY_API_TOKEN=${SOCKET_SECURITY_API_TOKEN}
    volumes:
      - ./socket.yml:/app/socket.yml:ro
      - ./ssl:/etc/nginx/ssl
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-fk", "https://localhost:8443/health"]
      interval: 30s
      timeout: 10s
      retries: 3

Step 4: DNS / Host Entry

For path-based routing, the firewall domain must resolve to the firewall host.

Local testing (add to /etc/hosts):

sudo sh -c 'printf "127.0.0.1   sfw.your_company.com\n::1         sfw.your_company.com\n" >> /etc/hosts'

Production: Create a DNS A/CNAME record for sfw.your_company.com pointing to the firewall host.

Step 5: Generate SSL Certificates

The firewall requires SSL certs at /etc/nginx/ssl/ inside the container. Generate them on the host before starting the container — the container process may not have write permissions to the mounted volume.

Self-Signed (Development/Testing)

mkdir -p ssl
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout ssl/privkey.pem \
  -out ssl/fullchain.pem \
  -subj "/CN=sfw.your_company.com" \
  -addext "subjectAltName=DNS:sfw.your_company.com,DNS:localhost"
chmod 644 ssl/fullchain.pem ssl/privkey.pem

Trusting Self-Signed Certificates

If using self-signed certs, trust them on client machines:

macOS:

sudo security add-trusted-cert -d -r trustRoot \
  -k /Library/Keychains/System.keychain ssl/fullchain.pem

Linux:

sudo cp ssl/fullchain.pem /usr/local/share/ca-certificates/socket-firewall.crt
sudo update-ca-certificates

Custom Certificates (Production)

mkdir -p ssl
cp /path/to/cert.pem ssl/fullchain.pem
cp /path/to/key.pem ssl/privkey.pem
chmod 644 ssl/fullchain.pem ssl/privkey.pem

Generate Self-Signed with Custom SANs

mkdir -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:sfw.company.com,DNS:npm.company.com,DNS:pypi.company.com"

Step 6: Start the Firewall

docker pull socketdev/socket-registry-firewall
docker compose up -d

Verify it's running:

curl -k https://localhost:8443/health
# Expected: {"status":"healthy","version":"..."}

Step 7: Configure Package Managers

npm

npm config set registry http://sfw.your_company.com:8080/npm/
npm config set strict-ssl false  # only for self-signed certs

Test:

npm install lodash --loglevel verbose   # should succeed
npm install lodahs                       # should be blocked (typosquat)

pip

pip config set global.index-url https://sfw.your_company.com:8443/pypi/simple
pip config set global.trusted-host "sfw.your_company.com"  # only for self-signed certs

Test:

pip install requests

Maven

Add to ~/.m2/settings.xml:

<settings>
  <mirrors>
    <mirror>
      <id>socket-firewall</id>
      <url>https://sfw.your_company.com:8443/maven</url>
      <mirrorOf>*</mirrorOf>
    </mirror>
  </mirrors>
</settings>

Test:

mvn install -Dmaven.wagon.http.ssl.insecure=true -Dmaven.wagon.http.ssl.allowall=true

Gradle

Edit settings.gradle:

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
    repositories {
        maven { url "https://sfw.your_company.com:8443/maven" }
    }
}

Cargo

# In .cargo/config.toml
[registries.socket]
index = "https://sfw.your_company.com:8443/cargo"

Go

export GOPROXY=https://sfw.your_company.com:8443/go,direct
export GOINSECURE=sfw.your_company.com
export GOSUMDB=off  # only for self-signed / private proxy

RubyGems

gem sources --add https://sfw.your_company.com:8443/rubygems/ --remove https://rubygems.org/
# or in Gemfile:
source "https://sfw.your_company.com:8443/rubygems/"

NuGet

dotnet nuget add source https://sfw.your_company.com:8443/nuget/v3/index.json -n socket-firewall

Editors (VS Code, Cursor, Antigravity)

Microsoft VS Code uses the vscode route. Code editors built from VS Code, such as Cursor, Antigravity and VSCodium, use the openvsx route. Never give a vscode route URL to any editor other than Microsoft VS Code. See Code Editor Extension Routes.

⚠️ The vscode route only blocks extensions once VS Code Marketplace scanning is turned on for your Socket organization. It is off by default; contact Socket to enable it.

VS Code loads a custom gallery only for a user signed in with a GitHub Enterprise account or a GitHub Copilot Business or Enterprise seat (Microsoft's Private Marketplace requirement). Anyone else sees "Your account does not have access to the extensions marketplace" and the firewall is never contacted. Use VS Code 1.103 or later (1.106 or later on Linux): versions 1.99 to 1.102 silently load Microsoft's Marketplace when the user is not signed in.

For managed devices, set the ExtensionGalleryServiceUrl policy to https://sfw.your_company.com:8443/vscode/vscode/gallery with Group Policy or Intune on Windows, a macOS configuration profile, or /etc/vscode/policy.json on Linux. To test on one machine, set the same URL in the user settings.json:

"extensions.gallery.serviceUrl": "https://sfw.your_company.com:8443/vscode/vscode/gallery"

This is an application-level setting, so a workspace .vscode/settings.json is ignored. Restart VS Code after either change.

The policy and setting cover the VS Code desktop app only. The code command line (code --install-extension) and the VS Code Server command line ignore them and go straight to Microsoft. To cover them, use the DNS override, or block Microsoft's hosts (marketplace.visualstudio.com, *.gallery.vsassets.io, *.gallerycdn.vsassets.io, *.vscode-unpkg.net) on editor machines so those installs fail instead of bypassing the firewall. If editor machines use an HTTP proxy, apply the blocks on the proxy.

Cursor: Settings → VS Code Settings → search for "marketplace" → set the service URL to https://sfw.your_company.com:8443/openvsx/vscode/gallery. For managed devices, use Cursor's macOS profile or Windows Group Policy with the same URL.

Antigravity: Settings → Antigravity IDE Settings → Editor → set the Gallery URL to https://sfw.your_company.com:8443/openvsx/vscode/gallery and the Item URL to https://sfw.your_company.com:8443/openvsx/vscode/item.

Test: search for secureannex hello-world. It should not appear, although it exists on Open VSX and the VS Code Marketplace. On the vscode route, this test is only meaningful once VS Code Marketplace scanning is enabled for your organization; before that, the extension appears.

Downstream with Private Registry Mirrors

If developers pull from an Artifactory or Nexus instance (not public registries), point the firewall's upstream at your private mirror:

path_routing:
  enabled: true
  domain: sfw.your_company.com
  routes:
    - path: /npm
      upstream: https://artifactory.company.com/artifactory/api/npm/npm-remote
      registry: npm
    - path: /pypi
      upstream: https://artifactory.company.com/artifactory/api/pypi/pypi-remote/simple
      registry: pypi
    - path: /maven
      upstream: https://artifactory.company.com/artifactory/maven-remote
      registry: maven

Developers hit the firewall, the firewall scans and proxies to Artifactory, Artifactory fetches from the public registry.

Developer  --->  Socket Firewall  --->  Artifactory  --->  Public Registry

Auto-Discovery

For large Artifactory/Nexus deployments with many repositories, use auto-discovery to sync routes automatically:

path_routing:
  enabled: true
  domain: sfw.your_company.com
  mode: artifactory  # or 'nexus'

  private_registry:
    api_url: https://artifactory.company.com/artifactory
    api_key: your-artifactory-api-key
    interval: 5m
    include_pattern: ".*"
    exclude_pattern: "(tmp|test)-.*"

Routes update automatically when repositories are added or removed.

Monitoring

Health Check

curl -k https://localhost:8443/health

Logs

docker compose logs -f socket-firewall          # all logs
docker compose logs socket-firewall | grep -i block   # blocked packages
docker compose logs socket-firewall | grep -i error   # errors

Splunk Integration

splunk:
  enabled: true
  hec_url: https://splunk.company.com:8088/services/collector/event
  hec_token: your-splunk-hec-token
  index: security
  source: socket-firewall

Webhook Integration

Send decision events to any HTTP endpoint:

webhook:
  enabled: true
  url: https://siem.company.com/api/events
  auth_header: "Bearer your-api-token"
  on_block: true
  on_warn: true

Troubleshooting

Container Won't Start

docker compose logs socket-firewall
docker compose exec socket-firewall env | grep SOCKET
docker compose exec socket-firewall socket-proxy-config-tool generate --config /app/socket.yml

Package Install Fails

docker compose logs socket-firewall | grep -i block    # check if blocked by policy
curl -kI https://localhost:8443/health                  # verify firewall is up
docker compose exec socket-firewall curl -I https://registry.npmjs.org  # test upstream

Firewall Not Blocking

docker compose exec socket-firewall env | grep SOCKET_SECURITY_API_TOKEN  # verify token
docker compose exec socket-firewall curl https://api.socket.dev/v0/health  # verify API access
cat socket.yml | grep fail_open  # check fail-open setting

Code Editor Extensions Not Loading

SymptomFix
VS Code: "Your account does not have access to the extensions marketplace"The signed-in user has no GitHub Enterprise account or Copilot Business or Enterprise seat. Sign in with an eligible account, or use the DNS override
VS Code ignores the gallery URLThe URL was set in a workspace .vscode/settings.json, which VS Code ignores for this setting. Use the user settings.json or the ExtensionGalleryServiceUrl policy, and restart VS Code
"Failed to fetch"The gallery URL uses the wrong route or path. Microsoft VS Code uses vscode; other editors use openvsx
Search is empty for every extensionOpen VSX is rate-limiting the firewall. Retry later
Known-malicious VS Code extensions still installVS Code Marketplace scanning is not enabled for your Socket organization. Contact Socket
VS Code Marketplace returns 400The request named an unsupported targetPlatform or had no version in its path
VS Code Marketplace returns 502The firewall could not establish which file a download is, or could not read the gallery response (over 64 MiB, or shed under memory pressure). Check the firewall's memory limit; see VS Code Marketplace Limits
Installing an older VS Code extension version fails with "not found"The version is older than the newest max_versions plus two per release channel. Raise max_versions

Did this page help you?