Deployment

The Artifact Firewall is published as a Docker image and a Helm chart, which run it in one of two deployment modes:

  • standalone, the default: in front of one or more package registries. Clients point at the firewall, which routes each request to one of the configured registries. It filters manifests and refuses blocked downloads, and streams package bodies through without caching them.
  • integrated: as part of a Virtual Registry, which routes and caches. The Virtual Registry fetches manifests through the firewall, and asks it before serving each artifact, from the cache or not.

The firewall is also bundled with the Virtual Registry, in its image and packages.

Docker image

The image is varnish/artifact-firewall on Docker Hub, for linux/amd64 and linux/arm64. It reads its configuration from /etc/varnish-artifact-firewall/default.yaml, and the proxy listens on port 6089.

Put the configuration file and the license in a directory:

# config/default.yaml
firewall:
  registries:
  - name: npmjs
    remote_url: https://registry.npmjs.org
    routes:
    - host: npm.example.com
  rulesets:
  - git:
      name: osv
      url: https://github.com/varnish/osv-rules.git
      sub_path: rulesets/npm/all.yaml

license:
  file: /etc/varnish-artifact-firewall/license.lic

Then mount the directory in place of the image’s own:

docker run --rm -p 6089:6089 \
  -v ./config:/etc/varnish-artifact-firewall:ro \
  varnish/artifact-firewall

A client that reaches the firewall as npm.example.com is routed to the npm registry:

npm install express --registry=http://npm.example.com:6089/

With the directory mounted rather than the file, the firewall sees an edited file even when the editor replaced it, so that it can reload it.

The container runs as the unprivileged user varnish, uid and gid 999. The firewall’s own files, such as the Git clones of its ruleset sources or storage.path, have to be under /var/lib/varnish-artifact-firewall, the default work_dir, or on a volume writable by that user.

Helm chart

The Helm chart deploys the firewall on Kubernetes. It is published as oci://registry-1.docker.io/varnish/artifact-firewall-chart, on a version series of its own, and installing it from there takes Helm 3.8 or later. Store the license as a secret:

kubectl create secret generic artifact-firewall-license \
  --from-file=./license.lic

Then install the chart with a values.yaml such as:

config:
  license:
    secret: artifact-firewall-license
  firewall:
    registries:
    - name: npmjs
      remote_url: https://registry.npmjs.org
      routes:
      - host: npm.example.com
helm install -f values.yaml artifact-firewall \
  oci://registry-1.docker.io/varnish/artifact-firewall-chart

Everything under config is written to the firewall’s configuration file. The chart’s own values, and how to set up rulesets, storage, probes, the admin API and metrics with it, are in its README:

helm show readme oci://registry-1.docker.io/varnish/artifact-firewall-chart

Integrated with a Virtual Registry

A Virtual Registry can integrate a firewall that runs on its own, for the registries that set enable_firewall. Varnish fetches their manifests through the firewall, which filters each one before Varnish caches it. Before serving an artifact, from its cache or not, Varnish asks the firewall’s admin API whether the version is allowed. The Virtual Registry keeps routing and caching.

The firewall has to run with deployment: integrated, since it relies on headers added to each request by the Virtual Registry, and both its listeners have to be reachable from Varnish:

firewall:
  deployment: integrated
  port: 6089
  api_address: 0.0.0.0:6090
  webhook:
    url: http://vr.example.com/purgez
    method: PURGE
    headers:
      Cache-Tags: resource_manifest
  rulesets:
  - git:
      name: npm-osv-rules
      url: https://github.com/varnish/osv-rules.git
      sub_path: rulesets/npm/all.yaml
  • The proxy listens on every interface unless address names one.
  • api_address binds loopback by default, so it has to be set. The admin API has no authentication, so keep both ports reachable from the Virtual Registry’s nodes only.
  • When the firewall reloads its rulesets, the webhook purges the manifests cached by Varnish under the previous ones. Point it at the Virtual Registry’s /purgez as above, and add the firewall’s address to purge.allow, which otherwise refuses a purge from anywhere but the node itself. The webhook takes one URL, so a firewall serving several Virtual Registry nodes needs it to point at something that sends the purge on to each of them, such as a Varnish Broadcaster.
  • Under deployment: integrated the firewall reads no license and sets up no OpenTelemetry, so it exports no metrics or traces, and audit_log_output: otel writes nothing. Give it a JSON audit_log_output such as stdout or a file.

The Virtual Registry names the firewall’s two listeners in the firewall section of its own configuration:

virtual_registry:
  registries:
  - name: npmjs
    enable_firewall: true
    remotes:
    - url: https://registry.npmjs.org

firewall:
  remote_address: firewall.example.com:6089
  remote_api_address: firewall.example.com:6090

With remote_address set, the Supervisor starts no firewall of its own and ignores the rest of its firewall section. Its license still needs the sup-firewall and sup-auth addons.

remote_address

Type: String

Address of the firewall’s proxy, in host:port form. Every registry that sets enable_firewall uses it, and Varnish sends it the manifests to filter. It has to be set together with remote_api_address, and cannot be combined with address.

remote_api_address

Type: String

Address of the firewall’s admin API, its api_address, in host:port form. Varnish calls /api/eval there to authorize each artifact download. It has to be set together with remote_address.

Bundled with the Virtual Registry

The Virtual Registry’s image and packages also carry the firewall. The Supervisor runs it in its own process, under deployment: integrated. The firewall reads the firewall section of the Supervisor’s configuration file, beside the Virtual Registry’s own sections:

varnish:
  http:
  - port: 80

virtual_registry:
  registries:
  - name: npmjs
    default: true
    enable_firewall: true
    remotes:
    - url: https://registry.npmjs.org

firewall:
  default_action: allow
  rulesets:
  - git:
      name: npm-osv-rules
      url: https://github.com/varnish/osv-rules.git
      sub_path: rulesets/npm/all.yaml

license:
  file: /etc/varnish-supervisor/license.lic

The rest belongs to the Supervisor as well:


®Varnish Software, Wallingatan 12, 111 60 Stockholm, Organization nr. 556805-6203