Stand Up Socket Firewall For The First Time

Stand up the Socket Registry Firewall in about 15 minutes and start blocking malicious packages at install time.

Socket Firewall (Registry Mode) is a container that sits between your package managers and the registries they pull from. Every package download is checked against Socket before it reaches the machine. A blocked package returns HTTP 403, so the install fails with a reason and a request ID.

This page gets one firewall running. The child pages cover what to do with it:

GoalPage
Block known-bad packagesFlat block
Hold brand-new releases for a few daysCooldown
Decide what gets blockedPolicy config
Keep verdicts across restarts and instancesRedis cache
Hide blocked versions so installs pick a safe oneMetadata filtering (needs Redis)
Point developers and CI at the firewallDeployments
Send decisions to a SIEMData
📘

Placeholders

Examples use sfw.example.com as the firewall hostname. Replace it everywhere with your own.

Prerequisites

  • Docker with Docker Compose
  • A Socket API key with the packages:list and entitlements:list scopes (Dashboard → Settings → API Tokens)
  • Outbound HTTPS from the firewall host to api.socket.dev and to the public registries

1. Create the project

mkdir -p ~/socket-fw/ssl && cd ~/socket-fw

cat > .env <<'ENV'
SOCKET_SECURITY_API_TOKEN=your_api_key_here
SOCKET_FAIL_OPEN=true
# Log clean allows too, not just blocks and warnings (see Data)
SOCKET_IGNORE_LOG_LEVEL=warn
ENV
🚧

Use the right variable name

The firewall container reads SOCKET_SECURITY_API_TOKEN. This is not the same variable the Socket CLI or CI integrations use.

2. Generate a certificate

The container expects fullchain.pem and privkey.pem in ssl/. For a POC a self-signed certificate is fine.

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

3. Write socket.yml

One route per ecosystem you need. This example covers npm and PyPI.

socket:
  api_url: https://api.socket.dev
  fail_open: true          # allow if the Socket API is unreachable; set false for strict posture

ports:
  http: 8080
  https: 8443

cache:
  ttl: 600                 # verdict cache, seconds

path_routing:
  enabled: true
  domain: sfw.example.com
  rewrite_scheme: https
  routes:
    - path: /npm
      upstream: https://registry.npmjs.org
      registry: npm
    - path: /pypi
      upstream: https://pypi.org
      registry: pypi

4. Write docker-compose.yml

Publishing the HTTPS port on 443 means clients never need a port in their URLs.

services:
  socket-firewall:
    image: socketdev/socket-registry-firewall:latest
    container_name: socket-registry-firewall
    ports:
      - "443:8443"
    env_file: .env
    environment:
      - CONFIG_FILE=/app/socket.yml
    volumes:
      - ./socket.yml:/app/socket.yml:ro
      - ./ssl:/etc/nginx/ssl:rw
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-fk", "https://localhost:8443/health"]
      interval: 30s
      timeout: 10s
      retries: 3
🚧

Why 443

The firewall rewrites package download URLs to path_routing.domain and drops any non-standard port. If clients reach it on :8443, metadata loads but downloads go to port 443 and fail (404 or connection refused, depending on what listens there). Publishing on 443 avoids this. If you must use another port, set path_routing.use_incoming_domain: true so rewritten URLs keep the host and port the client used.

5. Start it

# Local testing only. In production, create a DNS record for sfw.example.com.
sudo sh -c 'printf "127.0.0.1   sfw.example.com\n" >> /etc/hosts'

docker compose up -d

# TLS isn't ready for the first few seconds, so retry
for i in $(seq 1 30); do curl -sk https://sfw.example.com/health && break; sleep 2; done
docker compose ps     # (healthy) can take about 45 s

Verify

docker compose logs socket-firewall | grep "Resolved org slug from API"
  • docker compose ps shows Up (healthy).
  • The health check returns SocketFirewall/<version> - Health OK (some builds return JSON with "status":"healthy").
  • The log line above is present. This is the check that proves the firewall can reach Socket and get verdicts.
🚧

Healthy is not the same as working

/health reports OK even when the firewall can't reach the Socket API or has no routes loaded. Always confirm with the log line above and a real block test (Flat block).

Troubleshooting

SymptomCauseFix
404 on every requestThe request's Host header is not path_routing.domainReach the firewall by sfw.example.com, not by IP or localhost
Metadata works, downloads failClients connect on a non-443 port and the rewritten URL drops itPublish on 443, or set path_routing.use_incoming_domain: true
Healthy, but nothing is checkedSocket API unreachable. With fail_open: true the firewall starts anyway and allows everythingCheck logs for Firewall access validation failed at startup, and allow outbound HTTPS to api.socket.dev
Nothing ever blocksWrong or missing API tokendocker compose exec socket-firewall env | grep SOCKET_SECURITY_API_TOKEN

Next

Flat block proves it blocks.

Reference


Did this page help you?