Files
pnpm/pnpr/docs/quick-start.md
Zoltan Kochan 7fb2bfab4a docs(pnpr): correct configuration keys, defaults, and commands (#17245)
Part of https://github.com/pnpm/tasks/issues/191.

Wrong claims:
- cli: drop the nonexistent `add-user --password` flag and document the
  terminal/stdin password read; `oci-gc --min-age` and `cache-gc --max-age`
  are the flags (the `-secs` forms are aliases); `--from` defaults to the
  `storage` key, not an internal field; `info` and `http` log the same
  access records; only global and server options have PNPR_* variables.
- configuration: `packumentTtl` defaults to 5m; the minimal config now
  sets `auth.htpasswd.file`, and the auth section says accounts live in
  memory without it or a backend; grouped hosted registries default their
  org to `<ecosystem>~<name>`; the handshake is served for any surface;
  the pipeline surface also satisfies "something must be served"; add
  `package.update_maintainers` to the audit list.
- tls-and-reverse-proxy: remove the invalid `publicUrl:` YAML key and the
  nonexistent `rate_limiting` setting.
- backup-and-restore: `pnpr verify` hashes by default (`--check-hashes`
  does not exist, `--skip-hashes` skips only the hash
  comparison); `migrate-storage
  --verify` compares bytes.
- webhooks: audit events do not cover publishes or token creation; the
  example uses a real action and the `actor` field.
- cli: the `RUST_LOG` example keeps `pnpr::audit=info`.
- install-acceleration: the `--public-url` host is exempt from the
  private-address refusal.
- shared-side-effects-cache: `pnpm pipeline` publishes workspace-task
  artifacts.

Missing facts: `routes.allowedPrivateNetworks`, the upstream `search` key
and canonical `maxAge`, built-in `npm.jsr.io` route, relative path
resolution, `log` defaults and `type`, `${VAR:-default}` substitution and
the full secret-field list, `oci` defaults, `artifacts.quota` bounds,
`migrate-storage` destination rules, `--osv false`, `--packument-ttl`
default, S3 `forcePathStyle`/`allowHttp` defaults, grouped org layout,
OIDC key table, container image section, `backend:` ignoring the htpasswd
and token files.

Duplicates and links: health probe bodies, reload procedure, and the
resolver allowlist now link to their one home; broken `#secret` anchor
fixed; links into the pnpm docs use absolute pnpm.io URLs.

Stale history: drop "pnpr v1" and the per-paragraph "Since alpha.N" /
"Since pnpm 12.x" prefixes, and the contributor-only extensibility text.

Also corrects the `as_filter_directive` doc comment, which claimed `http`
quiets the rest of the crate.
2026-10-23 00:11:00 +02:00

104 lines
3.2 KiB
Markdown

---
id: quick-start
title: Quick start
---
## Write a config
pnpr routes packages through declared
[registries](configuration.md#registries-and-defaultregistry): every origin
(a locally-hosted registry, an upstream like npmjs) is declared explicitly and
claims the package names it serves, and a router resolves each name to exactly
one of them. Save this as `pnpr.yaml`:
```yaml title="pnpr.yaml"
storage: ./storage
auth:
htpasswd:
file: ./htpasswd
# Allow one user to self-register, for the publish step below.
max_users: 1
registries:
# Packages published to this server. The `packages:` map is this
# registry's namespace: only these names can live here.
local:
type: hosted
packages:
'@mycompany/*':
publish: $authenticated
# The public npm registry. No `packages:` map — it serves every name,
# so it must be the last source in the router below.
npmjs:
type: upstream
url: https://registry.npmjs.org/
public: true
# A package resolves to the first source that claims its name:
# your scope goes to the local registry, everything else to npm.
main:
type: router
sources: [local, npmjs]
# The bare server URL serves the router.
defaultRegistry: main
```
Replace `@mycompany` with your own scope. There is no fall-through between
registries: a `@mycompany/*` package that isn't published locally is a
definitive 404, never a request to npmjs. This is what closes
dependency confusion.
## Start the server
```sh
pnpr -c ./pnpr.yaml
```
It listens on `127.0.0.1:7677`. Running plain `pnpr` with no config works
too. The bundled config proxies npmjs and provides a local hosted registry at
`/npm/~local/`, whose packages need a login. It allows no self-registration,
so create accounts with [`pnpr add-user`](cli.md#add-user).
## Point a client at it
Configure pnpm (or npm/yarn) to use the local server as its registry:
```sh
pnpm config set registry http://127.0.0.1:7677/npm/
```
Now `pnpm install` fetches packages through pnpr. Packages proxied from the
upstream are cached, so subsequent installs are served locally.
Each registry is also directly addressable at
`http://127.0.0.1:7677/npm/~<name>/`. For example, you can point only your scope
at the hosted registry instead of using the router.
## Publish a package
Create a user and publish:
```sh
pnpm login --registry http://127.0.0.1:7677/npm/
pnpm publish --registry http://127.0.0.1:7677/npm/
```
The publish routes through the router to the `local` hosted registry.
Publishing a package that resolves to an upstream, or whose name no registry
claims, is rejected.
## Where to go next
- [CLI reference](cli.md): every flag `pnpr` accepts.
- [Configuration](configuration.md): write your own config, including registries,
access rules, and auth.
- [Reverse proxy and TLS](tls-and-reverse-proxy.md): set up Nginx, Caddy, Traefik, or a cloud load balancer for production.
- [Webhooks and event notifications](webhooks.md): stream audit events and storage notifications to external webhooks.
- [Backup and restore](backup-and-restore.md): snapshot and restore package storage and user records.
- [Install acceleration](install-acceleration.md): let pnpr resolve your
dependency graph to speed up installs.