pnpm¶
Prerequisites¶
Ensure both package.json and pnpm-lock.yaml are present in the project directory.
The lockfileVersion field must be within the range of >= 9.0 and < 10.0. Earlier
versions are not supported. Newer versions could introduce breaking changes to the
lockfile format, so Hermeto might not be able to process them correctly.
Usage¶
Using Hermeto locally with pnpm requires no special configuration or additional software (including pnpm itself). Hermeto downloads dependencies only explicitly declared in pnpm-lock.yaml without invoking the pnpm binary, which avoids arbitrary code execution during prefetch and keeps the process predictable.
Make sure the file is up to date by running pnpm install. Otherwise, the hermetic build will likely fail.
Each dependency is downloaded as a tar archive into the output directory under deps/pnpm/. Packages from the npm and JSR registries are stored in separate subdirectories.
hermeto-output/deps/pnpm/
├── npm/
│ ├── react-18.3.1.tgz
│ └── ...
├── jsr/
│ ├── ...
Hermeto modifies .npmrc and pnpm-lock.yaml to point registries and tarball URLs to local files in the output directory. Other settings in .npmrc are preserved. If the file does not exist, it is created.
These updates happen automatically when calling Hermeto's inject-files command. See the Example section below.
A snippet of .npmrc after modification:
registry=file:///tmp/hermeto-output/deps/pnpm/npm/
@jsr:registry=file:///tmp/hermeto-output/deps/pnpm/jsr/
A snippet of pnpm-lock.yaml after modification:
packages:
react@18.3.1:
resolution:
integrity: sha512-...
- tarball: https://registry.npmjs.org/react/-/react-18.3.1.tgz
+ tarball: react-18.3.1.tgz
SBOM¶
Hermeto stores the SBOM in the output directory (hermeto-output/bom.json) with information about all dependencies. See the SBOM page for more details.
Proxy¶
Configure the proxy via a config file. See the Configuration page for supported config file locations.
pnpm:
proxy_url: https://my-npm-proxy.example.com
proxy_login: user
proxy_password: pass
Alternatively, configure the proxy via environment variables:
export HERMETO_PNPM__PROXY_URL=https://my-npm-proxy.example.com
export HERMETO_PNPM__PROXY_LOGIN=user
export HERMETO_PNPM__PROXY_PASSWORD=pass
Note
The proxy is used only for packages from the official npm registry. Other package sources do not work with the proxy.
Example¶
Fetch dependencies¶
Fetch all dependencies from pnpm-lock.yaml and generate an SBOM.
hermeto fetch-deps pnpm
tree hermeto-output/deps/pnpm
cat hermeto-output/bom.json
Generate environment variables¶
Note
This step is only required when using pnpm v11.3 and later.
Starting with pnpm 11.3, the trustLockfile setting controls whether pnpm install
re-applies supply-chain verification checks to lockfile entries. Hermeto injects
pnpm-lock.yaml to point tarball URLs to local files, so this verification must be
skipped during the hermetic build.
Hermeto sets PNPM_CONFIG_TRUST_LOCKFILE=true for this purpose.
hermeto generate-env ./hermeto-output --for-output-dir /tmp/hermeto-output --output hermeto.env
cat hermeto.env
Inject project files¶
Modify pnpm-lock.yaml and .npmrc for the hermetic build.
hermeto inject-files ./hermeto-output --for-output-dir /tmp/hermeto-output
git diff
Build the image offline¶
This example uses generic backend artifact to install a specific
version of pnpm using npm binary. There is an official pnpm base image, but
without node runtime and no tags for pnpm v10. Unofficial images on Docker Hub
are also an option.
Dockerfile:
FROM docker.io/library/node:24
# ...
RUN npm install -g /tmp/hermeto-output/deps/generic/pnpm-11.x.y.tgz
WORKDIR /app
COPY . .
RUN source /tmp/hermeto.env && pnpm install
# ...
Note
When using pnpm v10, you can omit sourcing hermeto.env and the volume mount in the command below.
podman build . \
--volume "$(realpath ./hermeto-output)":/tmp/hermeto-output:Z \
--volume "$(realpath ./hermeto.env)":/tmp/hermeto.env:Z \
--network none \
--tag pnpm-app
For more detailed instructions, see the Usage page or run hermeto --help.