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/hostsentry for the firewall domain (for path-based routing)
Step 1: Set Your API Token
export SOCKET_SECURITY_API_TOKEN=your-api-key-hereOr create a .env file:
cat > .env <<EOF
SOCKET_SECURITY_API_TOKEN=your-api-key-here
EOFStep 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: 4096Include 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: 3Step 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.pemTrusting 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.pemLinux:
sudo cp ssl/fullchain.pem /usr/local/share/ca-certificates/socket-firewall.crt
sudo update-ca-certificatesCustom 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.pemGenerate 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 -dVerify 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 certsTest:
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 certsTest:
pip install requestsMaven
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=trueGradle
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 proxyRubyGems
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-firewallEditors (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
vscoderoute 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: mavenDevelopers 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/healthLogs
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 # errorsSplunk Integration
splunk:
enabled: true
hec_url: https://splunk.company.com:8088/services/collector/event
hec_token: your-splunk-hec-token
index: security
source: socket-firewallWebhook 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: trueTroubleshooting
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.ymlPackage 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 upstreamFirewall 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 settingCode Editor Extensions Not Loading
| Symptom | Fix |
|---|---|
| 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 URL | The 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 extension | Open VSX is rate-limiting the firewall. Retry later |
| Known-malicious VS Code extensions still install | VS Code Marketplace scanning is not enabled for your Socket organization. Contact Socket |
VS Code Marketplace returns 400 | The request named an unsupported targetPlatform or had no version in its path |
VS Code Marketplace returns 502 | The 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 |
Updated 5 days ago