mirror of
https://github.com/git-pkgs/proxy.git
synced 2026-08-01 10:08:08 -04:00
Add http_timeout config option (and PROXY_HTTP_TIMEOUT env var) to set the per-request timeout on the shared HTTP client used by protocol handlers for upstream metadata fetches and pass-through file requests. Defaults to the previous hardcoded 30s; "0" disables the timeout. Fixes #187
383 lines
12 KiB
Markdown
383 lines
12 KiB
Markdown
# Configuration
|
|
|
|
The proxy can be configured via command line flags, environment variables, or a configuration file. Command line flags take precedence over environment variables, which take precedence over the configuration file.
|
|
|
|
## Configuration File
|
|
|
|
Create a YAML or JSON file and pass it with `-config`:
|
|
|
|
```bash
|
|
proxy serve -config config.yaml
|
|
```
|
|
|
|
See `config.example.yaml` in the repository root for a complete example.
|
|
|
|
## Server Settings
|
|
|
|
| Config | Environment | Flag | Default | Description |
|
|
|--------|-------------|------|---------|-------------|
|
|
| `listen` | `PROXY_LISTEN` | `-listen` | `:8080` | Address to listen on |
|
|
| `base_url` | `PROXY_BASE_URL` | `-base-url` | `http://localhost:8080` | Public URL package managers use to reach this proxy |
|
|
| `ui_base_url` | `PROXY_UI_URL` | - | (defaults to `base_url`) | Public URL where the web UI is reached. Set separately when the UI lives behind a different hostname than package endpoints (e.g. public domain vs Docker network alias). Used for canonical/og:url tags and the install guide banner. The proxy still serves package endpoints on the same listener, so any reverse proxy fronting the UI publicly should restrict the public route to `PathPrefix(/ui)` to avoid exposing package endpoints. |
|
|
|
|
## Storage
|
|
|
|
The proxy stores cached artifacts using gocloud.dev/blob, supporting local filesystem and S3-compatible storage.
|
|
|
|
### Local Filesystem
|
|
|
|
```yaml
|
|
storage:
|
|
url: "file:///var/cache/proxy"
|
|
```
|
|
|
|
Or using the legacy path option:
|
|
|
|
```yaml
|
|
storage:
|
|
path: "./cache/artifacts"
|
|
```
|
|
|
|
| Config | Environment | Flag | Description |
|
|
|--------|-------------|------|-------------|
|
|
| `storage.url` | `PROXY_STORAGE_URL` | `-storage-url` | Storage URL (file:// or s3://) |
|
|
| `storage.path` | `PROXY_STORAGE_PATH` | `-storage-path` | Local path (deprecated, use url) |
|
|
| `storage.max_size` | `PROXY_STORAGE_MAX_SIZE` | - | Max cache size (e.g., "10GB") |
|
|
|
|
### Amazon S3
|
|
|
|
```yaml
|
|
storage:
|
|
url: "s3://my-bucket"
|
|
```
|
|
|
|
Configure credentials via environment variables:
|
|
|
|
```bash
|
|
export AWS_ACCESS_KEY_ID=your-key
|
|
export AWS_SECRET_ACCESS_KEY=your-secret
|
|
export AWS_REGION=us-east-1
|
|
```
|
|
|
|
### S3-Compatible (MinIO, etc.)
|
|
|
|
```yaml
|
|
storage:
|
|
url: "s3://my-bucket?endpoint=http://localhost:9000&disableSSL=true&s3ForcePathStyle=true"
|
|
```
|
|
|
|
## Database
|
|
|
|
The proxy supports SQLite (default) and PostgreSQL for storing package metadata.
|
|
|
|
### SQLite
|
|
|
|
```yaml
|
|
database:
|
|
driver: "sqlite"
|
|
path: "./cache/proxy.db"
|
|
```
|
|
|
|
| Config | Environment | Flag | Description |
|
|
|--------|-------------|------|-------------|
|
|
| `database.driver` | `PROXY_DATABASE_DRIVER` | `-database-driver` | `sqlite` or `postgres` |
|
|
| `database.path` | `PROXY_DATABASE_PATH` | `-database-path` | SQLite file path |
|
|
|
|
### PostgreSQL
|
|
|
|
```yaml
|
|
database:
|
|
driver: "postgres"
|
|
url: "postgres://user:password@localhost:5432/proxy?sslmode=disable"
|
|
```
|
|
|
|
| Config | Environment | Flag | Description |
|
|
|--------|-------------|------|-------------|
|
|
| `database.url` | `PROXY_DATABASE_URL` | `-database-url` | PostgreSQL connection URL |
|
|
|
|
## Logging
|
|
|
|
```yaml
|
|
log:
|
|
level: "info"
|
|
format: "text"
|
|
```
|
|
|
|
| Config | Environment | Flag | Values |
|
|
|--------|-------------|------|--------|
|
|
| `log.level` | `PROXY_LOG_LEVEL` | `-log-level` | `debug`, `info`, `warn`, `error` |
|
|
| `log.format` | `PROXY_LOG_FORMAT` | `-log-format` | `text`, `json` |
|
|
|
|
## Upstream Registries
|
|
|
|
Override default upstream registry URLs:
|
|
|
|
```yaml
|
|
upstream:
|
|
npm: "https://registry.npmjs.org"
|
|
maven: "https://repo1.maven.org/maven2"
|
|
gradle_plugin_portal: "https://plugins.gradle.org/m2"
|
|
cargo: "https://index.crates.io"
|
|
cargo_download: "https://static.crates.io/crates"
|
|
```
|
|
|
|
## Authentication
|
|
|
|
Configure authentication for private upstream registries. Auth is matched by URL prefix, and credentials can reference environment variables using `${VAR_NAME}` syntax.
|
|
|
|
### Bearer Token
|
|
|
|
Used by npm, GitHub Package Registry, and many other registries:
|
|
|
|
```yaml
|
|
upstream:
|
|
auth:
|
|
"https://registry.npmjs.org":
|
|
type: bearer
|
|
token: "${NPM_TOKEN}"
|
|
"https://npm.pkg.github.com":
|
|
type: bearer
|
|
token: "${GITHUB_TOKEN}"
|
|
```
|
|
|
|
### Basic Authentication
|
|
|
|
Used by PyPI, Artifactory, and others:
|
|
|
|
```yaml
|
|
upstream:
|
|
auth:
|
|
"https://pypi.org":
|
|
type: basic
|
|
username: "__token__"
|
|
password: "${PYPI_TOKEN}"
|
|
"https://artifactory.mycompany.com":
|
|
type: basic
|
|
username: "deploy"
|
|
password: "${ARTIFACTORY_PASSWORD}"
|
|
```
|
|
|
|
### Custom Header
|
|
|
|
For registries that use non-standard authentication headers:
|
|
|
|
```yaml
|
|
upstream:
|
|
auth:
|
|
"https://maven.mycompany.com":
|
|
type: header
|
|
header_name: "X-Auth-Token"
|
|
header_value: "${MAVEN_TOKEN}"
|
|
```
|
|
|
|
### URL Matching
|
|
|
|
Auth configs are matched by URL prefix. The longest matching prefix wins, so you can configure different credentials for different paths:
|
|
|
|
```yaml
|
|
upstream:
|
|
auth:
|
|
# All requests to this registry
|
|
"https://registry.mycompany.com":
|
|
type: bearer
|
|
token: "${REGISTRY_TOKEN}"
|
|
# Override for a specific scope
|
|
"https://registry.mycompany.com/@private":
|
|
type: bearer
|
|
token: "${PRIVATE_TOKEN}"
|
|
```
|
|
|
|
## Gradle Build Cache
|
|
|
|
The `/gradle` endpoint supports optional safeguards for upload control and cache retention.
|
|
|
|
```yaml
|
|
gradle:
|
|
build_cache:
|
|
read_only: false
|
|
max_upload_size: "100MB"
|
|
max_age: "168h"
|
|
max_size: "20GB"
|
|
sweep_interval: "10m"
|
|
```
|
|
|
|
| Config | Environment | Description |
|
|
|--------|-------------|-------------|
|
|
| `gradle.build_cache.read_only` | `PROXY_GRADLE_BUILD_CACHE_READ_ONLY` | Disable PUT uploads and keep GET/HEAD read-only |
|
|
| `gradle.build_cache.max_upload_size` | `PROXY_GRADLE_BUILD_CACHE_MAX_UPLOAD_SIZE` | Maximum accepted PUT body size (must be > 0) |
|
|
| `gradle.build_cache.max_age` | `PROXY_GRADLE_BUILD_CACHE_MAX_AGE` | Delete entries older than this duration (default `168h`, set `0` to disable) |
|
|
| `gradle.build_cache.max_size` | `PROXY_GRADLE_BUILD_CACHE_MAX_SIZE` | Total size cap for `_gradle/http-build-cache`, deleting oldest first (`0` disables) |
|
|
| `gradle.build_cache.sweep_interval` | `PROXY_GRADLE_BUILD_CACHE_SWEEP_INTERVAL` | Frequency for background eviction sweeps |
|
|
|
|
`max_age` and `max_size` are independent and can be combined. When both are set, age-based eviction runs first, then size-based eviction trims remaining entries oldest-first.
|
|
|
|
## Cooldown
|
|
|
|
The cooldown feature hides package versions published too recently, giving the community time to spot malicious releases before they reach your projects. When a version is within its cooldown period, it's stripped from metadata responses so package managers won't install it.
|
|
|
|
```yaml
|
|
cooldown:
|
|
default: "3d"
|
|
ecosystems:
|
|
npm: "7d"
|
|
cargo: "0"
|
|
packages:
|
|
"pkg:npm/lodash": "0"
|
|
"pkg:npm/@babel/core": "14d"
|
|
```
|
|
|
|
| Config | Environment | Description |
|
|
|--------|-------------|-------------|
|
|
| `cooldown.default` | `PROXY_COOLDOWN_DEFAULT` | Global default cooldown |
|
|
| `cooldown.ecosystems` | - | Per-ecosystem overrides |
|
|
| `cooldown.packages` | - | Per-package overrides (keyed by PURL) |
|
|
|
|
Durations support days (`7d`), hours (`48h`), and minutes (`30m`). Set to `0` to disable.
|
|
|
|
Resolution order: package override, then ecosystem override, then global default. This lets you set a conservative default while exempting trusted packages.
|
|
|
|
Currently supported for npm, PyPI, pub.dev, Composer, Cargo, NuGet, Conda, RubyGems, and Hex. These ecosystems include publish timestamps in their metadata.
|
|
|
|
Note: Hex cooldown requires disabling registry signature verification since the proxy re-encodes the protobuf payload without the original signature. Set `HEX_NO_VERIFY_REPO_ORIGIN=1` or configure your repo with `no_verify: true`.
|
|
|
|
## Metadata Caching
|
|
|
|
By default the proxy fetches metadata fresh from upstream on every request. Enable `cache_metadata` to store metadata responses in the database and storage backend for offline fallback. When upstream is unreachable, the proxy serves the last cached copy. ETag-based revalidation avoids re-downloading unchanged metadata.
|
|
|
|
```yaml
|
|
cache_metadata: true
|
|
```
|
|
|
|
Or via environment variable: `PROXY_CACHE_METADATA=true`.
|
|
|
|
The `proxy mirror` command always enables metadata caching regardless of this setting.
|
|
|
|
### Metadata TTL
|
|
|
|
When metadata caching is enabled, `metadata_ttl` controls how long a cached response is considered fresh before revalidating with upstream. During the TTL window, cached metadata is served directly without contacting upstream, reducing latency and upstream load.
|
|
|
|
```yaml
|
|
metadata_ttl: "5m" # default
|
|
```
|
|
|
|
Or via environment variable: `PROXY_METADATA_TTL=10m`.
|
|
|
|
Set to `"0"` to always revalidate with upstream (ETag-based conditional requests still avoid re-downloading unchanged content).
|
|
|
|
When upstream is unreachable and the cached entry is past its TTL, the proxy serves the stale cached copy with a `Warning: 110 - "Response is Stale"` header so clients can tell the data may be outdated.
|
|
|
|
### Metadata size limit
|
|
|
|
Upstream metadata responses are buffered in memory before being rewritten and served. `metadata_max_size` caps that buffer to protect against OOM from a misbehaving upstream. Some npm packages with thousands of versions (for example `renovate`) exceed the 100 MB default, so raise this if you see `metadata response exceeds size limit` in the logs.
|
|
|
|
```yaml
|
|
metadata_max_size: "100MB" # default
|
|
```
|
|
|
|
Or via environment variable: `PROXY_METADATA_MAX_SIZE=250MB`.
|
|
|
|
## Upstream HTTP timeout
|
|
|
|
Protocol handlers use a shared HTTP client for upstream requests such as metadata fetches and pass-through file downloads. `http_timeout` sets that client's per-request timeout. Raise it if slow upstreams or large metadata responses cause `context deadline exceeded` errors.
|
|
|
|
```yaml
|
|
http_timeout: "30s" # default
|
|
```
|
|
|
|
Or via environment variable: `PROXY_HTTP_TIMEOUT=2m`.
|
|
|
|
Set to `"0"` to disable the timeout entirely (requests then rely only on the server's write timeout).
|
|
|
|
## Mirror API
|
|
|
|
The `/api/mirror` endpoints are disabled by default. Enable them to allow starting mirror jobs via HTTP:
|
|
|
|
```yaml
|
|
mirror_api: true
|
|
```
|
|
|
|
Or via environment variable: `PROXY_MIRROR_API=true`.
|
|
|
|
When disabled, the endpoints are not registered and return 404.
|
|
|
|
## Mirror Command
|
|
|
|
The `proxy mirror` command pre-populates the cache from various sources. It accepts the same storage and database flags as `serve`.
|
|
|
|
| Flag | Default | Description |
|
|
|------|---------|-------------|
|
|
| `--sbom` | | Path to CycloneDX or SPDX SBOM file |
|
|
| `--concurrency` | `4` | Number of parallel downloads |
|
|
| `--dry-run` | `false` | Show what would be mirrored without downloading |
|
|
| `--config` | | Path to configuration file |
|
|
| `--storage-url` | | Storage URL |
|
|
| `--database-driver` | | Database driver |
|
|
| `--database-path` | | SQLite database file |
|
|
| `--database-url` | | PostgreSQL connection URL |
|
|
|
|
Positional arguments are treated as PURLs:
|
|
|
|
```bash
|
|
proxy mirror pkg:npm/lodash@4.17.21 pkg:cargo/serde@1.0.0
|
|
```
|
|
|
|
## Docker
|
|
|
|
### SQLite with Local Storage
|
|
|
|
```bash
|
|
docker compose up
|
|
```
|
|
|
|
### PostgreSQL with Local Storage
|
|
|
|
```bash
|
|
docker compose --profile postgres up
|
|
```
|
|
|
|
### PostgreSQL with S3 (MinIO)
|
|
|
|
```bash
|
|
docker compose --profile s3 up
|
|
```
|
|
|
|
## Example Configurations
|
|
|
|
### Minimal (defaults)
|
|
|
|
```yaml
|
|
listen: ":8080"
|
|
```
|
|
|
|
### Production with PostgreSQL and S3
|
|
|
|
```yaml
|
|
listen: ":8080"
|
|
base_url: "https://proxy.example.com"
|
|
|
|
storage:
|
|
url: "s3://my-cache-bucket"
|
|
max_size: "100GB"
|
|
|
|
database:
|
|
driver: "postgres"
|
|
url: "postgres://proxy:secret@db.example.com:5432/proxy?sslmode=require"
|
|
|
|
log:
|
|
level: "info"
|
|
format: "json"
|
|
```
|
|
|
|
### Private npm Registry
|
|
|
|
```yaml
|
|
listen: ":8080"
|
|
base_url: "http://localhost:8080"
|
|
|
|
upstream:
|
|
npm: "https://npm.pkg.github.com"
|
|
auth:
|
|
npm:
|
|
type: bearer
|
|
token: "${GITHUB_TOKEN}"
|
|
```
|