mirror of
https://github.com/git-pkgs/proxy.git
synced 2026-11-10 08:09:17 -05:00
A generic upstream forwards any path below /generic/{name}/. The
documented mise setup puts a GITHUB_TOKEN on api.github.com to raise
the rate limit, so anyone who could reach the proxy could make any GET
request with that token, including for private repositories it can
read, and the answers went into the shared metadata cache. upstream.git
already refuses an upstream with credentials unless it lists its repos.
upstream.generic_paths now lists, per generic upstream, the paths it
may serve, with the same pattern syntax as git repos. Other paths
answer 404 without reaching the upstream, and so does a path holding
'%', '?', '#' or a backslash, which the upstream could read as a
different path than the one that matched. Config validation refuses a
generic upstream that upstream.auth has credentials for unless it has
generic_paths, which also covers a github.com token reaching the
generic github upstream. Upstreams without credentials keep serving
every path.
The docs and example config show the paths mise needs and recommend a
fine-grained token limited to public repositories.
522 lines
19 KiB
YAML
522 lines
19 KiB
YAML
# Proxy server configuration
|
|
# Copy to config.yaml and modify as needed
|
|
|
|
# Server listen address
|
|
listen: ":8080"
|
|
|
|
# Public URL where package endpoints are reachable.
|
|
# Used for rewriting package metadata URLs and shown in install guide snippets
|
|
# so users know what to point their package manager at.
|
|
base_url: "http://localhost:8080"
|
|
|
|
# Timeout for individual upstream HTTP requests made by protocol handlers
|
|
# (metadata fetches, pass-through file requests). Uses Go duration syntax.
|
|
# Set to "0" to disable the timeout. Default: "30s".
|
|
# http_timeout: "30s"
|
|
|
|
# Response write deadline, including download and scan time before sending data.
|
|
# Set to "0" to disable. Default: "5m".
|
|
# write_timeout: "5m"
|
|
|
|
# Timeout for each upstream artifact download while serving requests; excludes
|
|
# scanning. Set to "0" to disable. Default: "5m". Does not limit proxy mirror.
|
|
# artifact_timeout: "5m"
|
|
|
|
# Register DELETE /api/cache and show Delete buttons on the UI's version page,
|
|
# for removing cached artifacts so they are fetched again. Has no
|
|
# authentication: restrict /api/cache and /ui at the ingress first.
|
|
# cache_delete: false
|
|
|
|
# Largest upstream artifact to fetch (e.g. "2GB"). Larger ones are refused
|
|
# and not cached. Default: unlimited.
|
|
# artifact_max_size: ""
|
|
|
|
# Memory for rewritten npm and Composer metadata, so each upstream document is
|
|
# rewritten and gzip-compressed once rather than on every request. Set to "0"
|
|
# to rewrite on every request. Default: "256MB".
|
|
# metadata_rewrite_cache_size: "256MB"
|
|
|
|
# Public URL where the web UI is reached. Defaults to base_url when unset.
|
|
# Set this separately when the UI is served on a different hostname than the
|
|
# package endpoints — for example, the UI on a public domain behind auth while
|
|
# build machines hit a Docker network alias for the package endpoints.
|
|
# ui_base_url: "https://proxy.example.com/ui"
|
|
|
|
# Attribute requests to the leftmost X-Forwarded-For entry rather than the TCP
|
|
# peer address, in the structured log, the access log and the request-source
|
|
# table on /ui/analytics.
|
|
#
|
|
# Enable this only when the proxy sits behind a load balancer or ingress that
|
|
# sets the header. Any client can send it: behind one it is the only way to see
|
|
# past the hop, in front of one it lets a caller forge its own address.
|
|
# trust_forwarded_for: false
|
|
|
|
# Show the request-source table on /ui/analytics: caller addresses, the tool
|
|
# each ran and how much each pulled.
|
|
#
|
|
# Off by default. The proxy has no authentication of its own, so leave this off
|
|
# unless /ui is gated by a reverse proxy; anyone who can reach the page can
|
|
# otherwise read the addresses of your build fleet.
|
|
# ui_request_sources: false
|
|
|
|
# List the latest failures behind each failure count on /ui/analytics (upstream,
|
|
# storage, integrity, health probe and scan errors): the package, its upstream
|
|
# URL or storage path, and the error. URLs lose credentials and query strings.
|
|
#
|
|
# Off by default, for the same reason as ui_request_sources.
|
|
# ui_failure_details: false
|
|
|
|
# Artifact storage configuration
|
|
storage:
|
|
# Storage backend URL
|
|
# Supported schemes:
|
|
# - file:///path/to/dir - Local filesystem (default)
|
|
# - s3://bucket-name - Amazon S3
|
|
# - s3://bucket?endpoint=http://localhost:9000 - S3-compatible (MinIO)
|
|
# - gs://bucket-name - Google Cloud Storage
|
|
# - azblob://container-name - Azure Blob Storage
|
|
#
|
|
# For S3, configure credentials via environment variables:
|
|
# AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION
|
|
#
|
|
# For GCS, authentication uses Application Default Credentials. On GKE with
|
|
# Workload Identity, bind the Kubernetes service account to a Google service
|
|
# account that has roles/storage.objectAdmin on the bucket. No extra config
|
|
# is needed in this file. For local development, run:
|
|
# gcloud auth application-default login
|
|
# If direct_serve is enabled, the service account also needs
|
|
# roles/iam.serviceAccountTokenCreator on itself so the IAM Credentials
|
|
# signBlob API can sign URLs without a private key.
|
|
url: ""
|
|
|
|
# Local filesystem path (used when url is empty)
|
|
# Deprecated: Use url with file:// scheme instead
|
|
path: "./cache/artifacts"
|
|
|
|
# Maximum cache size (e.g., "10GB", "500MB")
|
|
# When exceeded, least recently used artifacts are evicted
|
|
# Empty or "0" means unlimited
|
|
max_size: ""
|
|
|
|
# Evict artifacts that have not been served for longer than a duration
|
|
# ("30d", "72h"), independent of max_size. Resolution order: package rule,
|
|
# then ecosystem rule, then default. "0" or empty means never evict by age.
|
|
# The default only applies to ecosystems that support retention; naming an
|
|
# ecosystem or package that does not is a configuration error. See
|
|
# docs/configuration.md for the supported ecosystems.
|
|
# Generic downloads require an explicit ecosystem or package rule;
|
|
# they never inherit default, since an upstream release may disappear.
|
|
retention:
|
|
default: ""
|
|
# ecosystems:
|
|
# npm: "30d"
|
|
# generic: "30d"
|
|
# packages:
|
|
# "pkg:npm/lodash": "0"
|
|
# "pkg:generic/owner%2Frepo": "90d"
|
|
# How often to look for expired artifacts; at least "1m".
|
|
sweep_interval: "10m"
|
|
|
|
# Store fetched artifacts. Set to false to stream every download from
|
|
# upstream without storing it; metadata filtering, cooldown and the
|
|
# denylist still apply. Useful when another cache sits in front of the
|
|
# proxy. false is incompatible with direct_serve, scanning, mirror_api and
|
|
# mirror.schedules.
|
|
cache_artifacts: true
|
|
|
|
# Redirect cached artifact downloads to presigned storage URLs (HTTP 302)
|
|
# instead of streaming through the proxy. Only effective for S3, GCS, and Azure.
|
|
# Leave disabled if clients reach the proxy through an authenticating gateway,
|
|
# since presigned URLs bypass it.
|
|
direct_serve: false
|
|
|
|
# How long presigned URLs remain valid (e.g. "5m", "1h"). Default: "15m".
|
|
direct_serve_ttl: "15m"
|
|
|
|
# Public base URL to substitute into presigned URLs. Set this when the
|
|
# proxy reaches storage at an internal address (127.0.0.1, a Docker
|
|
# service name) but clients must use a public hostname. Only scheme and
|
|
# host are used; the signed path and query are preserved. For S3/MinIO
|
|
# the reverse proxy at this address must forward requests with the
|
|
# internal Host header or the SigV4 signature will not validate.
|
|
# direct_serve_base_url: "https://minio.example.com"
|
|
|
|
# Database configuration
|
|
database:
|
|
# Database driver: "sqlite" (default) or "postgres"
|
|
driver: "sqlite"
|
|
|
|
# SQLite database file path (used when driver is "sqlite")
|
|
path: "./cache/proxy.db"
|
|
|
|
# PostgreSQL connection URL (used when driver is "postgres")
|
|
# Example: "postgres://user:password@localhost:5432/proxy?sslmode=disable"
|
|
url: ""
|
|
|
|
# How often cache hit counts and last-access times are written, batched in
|
|
# one transaction. "0" writes each hit as it happens.
|
|
hit_flush_interval: "1s"
|
|
|
|
# Logging configuration
|
|
log:
|
|
# Minimum log level: "debug", "info", "warn", "error"
|
|
level: "info"
|
|
|
|
# Log format: "text" or "json"
|
|
format: "text"
|
|
|
|
# JSONL access log. Leave path empty to disable it.
|
|
access_log:
|
|
path: ""
|
|
|
|
# Upstream URLs for built-in routes and authentication
|
|
upstream:
|
|
# Hosts allowed to resolve to private, ULA, or CGNAT addresses
|
|
allow_private_hosts: []
|
|
|
|
# Permit upstream requests and redirects to loopback addresses
|
|
allow_loopback: false
|
|
|
|
# npm registry URL
|
|
npm: "https://registry.npmjs.org"
|
|
# Always request full npm packuments so served metadata carries publish
|
|
# times ("time" map) even when cooldown is disabled. Needed by clients that
|
|
# gate on publish age, e.g. Yarn's npmMinimalAgeGate. Default: false.
|
|
# npm_full_metadata: true
|
|
|
|
# npm packages served only from a private registry, by name pattern.
|
|
# Matching packages are never looked up on the npm registry above.
|
|
# npm_routes:
|
|
# "@example/*": "https://npm.example.com/registry"
|
|
|
|
# Cargo sparse index URL
|
|
cargo: "https://index.crates.io"
|
|
|
|
# Cargo crate download URL
|
|
cargo_download: "https://static.crates.io/crates"
|
|
|
|
# RubyGems registry URL
|
|
gem: "https://rubygems.org"
|
|
|
|
# Go module proxy URL
|
|
go: "https://proxy.golang.org"
|
|
|
|
# Hex repository URL
|
|
hex: "https://repo.hex.pm"
|
|
|
|
# Hex API URL used for package timestamps
|
|
hex_api: "https://hex.pm"
|
|
|
|
# pub registry URL
|
|
pub: "https://pub.dev"
|
|
|
|
# PyPI index and API URL
|
|
pypi: "https://pypi.org"
|
|
|
|
# PyPI package download URL
|
|
pypi_download: "https://files.pythonhosted.org"
|
|
|
|
# Maven repository URL (used by /maven endpoint)
|
|
maven: "https://repo1.maven.org/maven2"
|
|
|
|
# Additional Maven repositories, served at /maven/{name}/. A name must not
|
|
# be the start of a group ID (such as "org" or "tools"), since it would hide
|
|
# those groups in the default repository.
|
|
# maven_repositories:
|
|
# grails: "https://repo.grails.org/grails/restricted"
|
|
|
|
# Gradle Plugin Portal Maven URL (fallback for plugin marker artifacts)
|
|
gradle_plugin_portal: "https://plugins.gradle.org/m2"
|
|
|
|
# NuGet API URL
|
|
nuget: "https://api.nuget.org"
|
|
|
|
# NuGet search API URL
|
|
nuget_search: "https://azuresearch-usnc.nuget.org"
|
|
|
|
# Packagist API URL
|
|
composer: "https://packagist.org"
|
|
|
|
# Packagist repository URL
|
|
composer_repository: "https://repo.packagist.org"
|
|
|
|
# Composer packages served only from a private repository, by name pattern.
|
|
# Matching packages are never looked up on composer_repository.
|
|
# composer_routes:
|
|
# "example/*": "https://composer.example.com/packages"
|
|
|
|
# Conan registry URL
|
|
conan: "https://center.conan.io"
|
|
|
|
# Chef Supermarket URL (used by /chef/). Point it at a private
|
|
# Supermarket to proxy that instead.
|
|
chef: "https://supermarket.chef.io"
|
|
|
|
# Conda channel base URL
|
|
conda: "https://conda.anaconda.org"
|
|
|
|
# CRAN mirror URL
|
|
cran: "https://cloud.r-project.org"
|
|
|
|
# Julia package server URL
|
|
julia: "https://pkg.julialang.org"
|
|
|
|
# Swift Package Registry URL (used by /swift endpoint)
|
|
swift: "https://tuist.dev/api/registry/swift"
|
|
|
|
# Default OCI registry URL for unprefixed /v2 requests
|
|
oci_default: "https://registry-1.docker.io"
|
|
|
|
# Debian/APT repository URL (used by /debian endpoint)
|
|
debian: "http://deb.debian.org/debian"
|
|
|
|
# Additional Debian/APT archives, served at /debian/{name}/.
|
|
# The names "pool" and "dists" are reserved for the main archive's own paths.
|
|
debian_repositories:
|
|
security: "https://security.debian.org/debian-security"
|
|
|
|
# RPM repository URL (used by /rpm endpoint)
|
|
rpm: "https://dl.fedoraproject.org/pub/fedora/linux"
|
|
|
|
# Homebrew JSON API URL (used by /homebrew endpoint)
|
|
homebrew_api: "https://formulae.brew.sh/api"
|
|
|
|
# Homebrew artifact registry URL (used for /v2/homebrew/core requests)
|
|
homebrew_artifact: "https://ghcr.io"
|
|
|
|
# Named HTTP Helm chart repositories (used by /helm/{name}/)
|
|
# helm:
|
|
# bitnami: "https://charts.bitnami.com/bitnami"
|
|
|
|
# Named OCI registries. Use the upstream/{name}/ repository prefix, e.g.
|
|
# oci://proxy.example.com/upstream/ghcr/owner/chart.
|
|
# oci:
|
|
# ghcr: "https://ghcr.io"
|
|
|
|
# Registries a named OCI upstream mirrors, e.g. when ghcr above points at
|
|
# an Artifactory remote of ghcr.io. containerd mirror requests whose ns
|
|
# parameter names one of these hosts are served by that upstream.
|
|
# oci_mirrors:
|
|
# ghcr: ["ghcr.io"]
|
|
|
|
# Named Alpine APK repositories (used by /apk/{name}/).
|
|
# Defaults to {"alpine": "https://dl-cdn.alpinelinux.org/alpine"} when empty;
|
|
# configuring any entry replaces that default.
|
|
# apk:
|
|
# alpine: "https://dl-cdn.alpinelinux.org/alpine"
|
|
# private: "https://apk.example.com"
|
|
|
|
# Named Arch Linux pacman mirrors (used by /arch/{name}/).
|
|
# Defaults to {"archlinux": "https://geo.mirror.pkgbuild.com"} when empty;
|
|
# configuring any entry replaces that default. Arch Linux ARM needs a
|
|
# regional HTTPS mirror of your choice, not the mirror.archlinuxarm.org
|
|
# redirector.
|
|
# arch:
|
|
# archlinux: "https://geo.mirror.pkgbuild.com"
|
|
# archlinuxarm: "https://<region>.mirror.archlinuxarm.org"
|
|
|
|
# Named FreeBSD pkg mirrors (used by /freebsd/{name}/), for ports and
|
|
# pkgbase repositories alike.
|
|
# Defaults to {"freebsd": "https://pkg.freebsd.org"} when empty;
|
|
# configuring any entry replaces that default.
|
|
# freebsd:
|
|
# freebsd: "https://pkg.freebsd.org"
|
|
# poudriere: "https://packages.example.com"
|
|
|
|
# Named generic HTTP upstreams (used by /generic/{name}/). The remaining
|
|
# request path and query are appended to the upstream URL. GitHub release
|
|
# assets ({owner}/{repo}/releases/download/{tag}/{asset}) are cached
|
|
# immutably; other paths use the metadata cache with stale-on-error.
|
|
# generic:
|
|
# github: "https://github.com"
|
|
# github-api: "https://api.github.com"
|
|
# apache: "https://archive.apache.org"
|
|
|
|
# Paths a generic upstream may serve, as path.Match patterns for the path
|
|
# after /generic/{name}/; a pattern ending in /** also matches everything
|
|
# nested below its prefix. Other paths answer 404. Required for an upstream
|
|
# that upstream.auth has credentials for, such as a GitHub token for
|
|
# api.github.com; use a fine-grained token with read-only access to public
|
|
# repositories.
|
|
# generic_paths:
|
|
# github-api:
|
|
# - "repos/*/*/releases"
|
|
# - "repos/*/*/releases/**"
|
|
# - "repos/*/*/tags"
|
|
|
|
# Version-pinned paths of generic upstreams, cached immutably like GitHub
|
|
# release assets. Each pattern must match the whole path after
|
|
# /generic/{name}/ and have `version` and `file` named groups; an optional
|
|
# `name` group names the package.
|
|
# generic_artifacts:
|
|
# apache:
|
|
# - 'dist/(?P<name>maven)/maven-3/(?P<version>[^/]+)/binaries/(?P<file>[^/]+)'
|
|
|
|
# Named Git servers (used by /git/{name}/{repo}), served read-only from
|
|
# cached bare repositories. repos limits which repositories may be served
|
|
# and is required when upstream.auth has credentials for the server.
|
|
# git:
|
|
# github: "https://github.com"
|
|
# wikimedia:
|
|
# url: "https://gerrit.wikimedia.org/r"
|
|
# repos: ["mediawiki/**"]
|
|
|
|
# Authentication for upstream registries
|
|
# Keys are absolute URL scopes. Scheme, host, effective port, and path
|
|
# segment boundaries must match; the longest matching scope wins.
|
|
# Values can reference environment variables using ${VAR_NAME} syntax.
|
|
#
|
|
# Supported auth types:
|
|
# - bearer: Authorization header with Bearer token
|
|
# - basic: Authorization header with Basic auth (username:password)
|
|
# - header: Custom header name and value
|
|
# - ecr: AWS ECR auto-refreshing token via the AWS SDK credential chain
|
|
auth:
|
|
# Example: npm with bearer token
|
|
# "https://registry.npmjs.org":
|
|
# type: bearer
|
|
# token: "${NPM_TOKEN}"
|
|
|
|
# Example: GitHub npm registry
|
|
# "https://npm.pkg.github.com":
|
|
# type: bearer
|
|
# token: "${GITHUB_TOKEN}"
|
|
|
|
# Example: PyPI with basic auth
|
|
# "https://pypi.org":
|
|
# type: basic
|
|
# username: "__token__"
|
|
# password: "${PYPI_TOKEN}"
|
|
|
|
# Example: Custom header for private registry
|
|
# "https://maven.mycompany.com":
|
|
# type: header
|
|
# header_name: "X-Auth-Token"
|
|
# header_value: "${MAVEN_TOKEN}"
|
|
|
|
# Example: private AWS ECR registry (12h tokens auto-refreshed via
|
|
# ecr:GetAuthorizationToken; credentials come from the AWS SDK default
|
|
# chain, so IRSA / instance profiles / AWS_* env vars all work; the region
|
|
# is inferred from the private ECR hostname)
|
|
# "https://123456789012.dkr.ecr.eu-west-1.amazonaws.com":
|
|
# type: ecr
|
|
|
|
# Git repository cache, used when upstream.git is set
|
|
# git:
|
|
# cache_dir: ./cache/git # local disk, used by this process only
|
|
# max_size: "" # evict least recently used repositories past this
|
|
# max_repo_size: 5GB # refuse a repository that grows past this
|
|
# refresh_wait: 5s # then serve the cached copy if the upstream check is slow
|
|
# stale_max_age: 24h # never serve a copy not checked for this long
|
|
|
|
# Gradle HttpBuildCache configuration
|
|
gradle:
|
|
build_cache:
|
|
# PUT uploads are rejected by default; set to false on the instance
|
|
# your CI jobs upload to
|
|
read_only: true
|
|
|
|
# Maximum accepted Gradle cache upload body size
|
|
# Required and must be > 0
|
|
max_upload_size: "100MB"
|
|
|
|
# Evict entries older than this age (set to "0" to disable age-based eviction)
|
|
max_age: "168h"
|
|
|
|
# Cap total Gradle cache size; oldest entries are deleted first
|
|
# ("0" disables size-based eviction)
|
|
# max_size: "20GB"
|
|
|
|
# How often eviction runs when max_age or max_size is set
|
|
sweep_interval: "10m"
|
|
|
|
# Pushing package archives to /api/hosted (disabled by default).
|
|
# A pushed version replaces the upstream one for every client, so a token is
|
|
# required to push and delete.
|
|
# hosted:
|
|
# enabled: true
|
|
# token: "${PROXY_HOSTED_TOKEN}"
|
|
# max_upload_size: "100MB"
|
|
# # Namespaces served from pushed packages only; the upstream is never asked
|
|
# # about them, so nobody can mix in versions by publishing the same name.
|
|
# npm_scopes: ["@acme"]
|
|
# composer_vendors: ["acme"]
|
|
|
|
# Re-mirror container image tags on a schedule, so a moved tag is picked up
|
|
# even when nobody pulls it. An unchanged tag costs one HEAD request.
|
|
# mirror:
|
|
# schedules:
|
|
# - images: ["pkg:docker/library/alpine@3.20", "pkg:docker/library/nginx@stable"]
|
|
# interval: "6h"
|
|
# platforms: ["linux/amd64"]
|
|
|
|
# Health endpoint configuration.
|
|
health:
|
|
# Minimum time between storage backend probes.
|
|
# The /health endpoint runs a write/read/verify/delete round-trip
|
|
# against the configured storage backend and caches the result for
|
|
# this interval. Set to "0" to probe on every request.
|
|
# Default: "30s".
|
|
storage_probe_interval: "30s"
|
|
|
|
# Version cooldown configuration
|
|
# Hides package versions published too recently, giving the community time
|
|
# to spot malicious releases before they're pulled into projects.
|
|
# Supported durations: "7d" (days), "48h" (hours), "30m" (minutes), "0" (disabled)
|
|
cooldown:
|
|
# Global default cooldown for all ecosystems
|
|
# default: "3d"
|
|
|
|
# Per-ecosystem overrides
|
|
# ecosystems:
|
|
# npm: "7d"
|
|
# cargo: "0"
|
|
|
|
# Per-package overrides (keyed by PURL). Keys are normalized, so npm scopes
|
|
# may use either @scope or the canonical %40scope form.
|
|
# packages:
|
|
# "pkg:npm/lodash": "0"
|
|
# "pkg:npm/@babel/core": "14d"
|
|
|
|
# Per-package glob overrides, after exact packages and before ecosystems.
|
|
# package_patterns:
|
|
# "pkg:npm/@example/*": "0"
|
|
|
|
# Exact versions to deny, independently of cooldown and scanning.
|
|
# Metadata filtering: npm, PyPI and Cargo. Shared artifact downloads, including
|
|
# cache hits, are blocked with 403; signed APT metadata is left unchanged.
|
|
# Use versioned PURLs without qualifiers/subpaths. Restart after changes.
|
|
# denylist:
|
|
# packages:
|
|
# - "pkg:pypi/requests@2.31.0"
|
|
# - "pkg:cargo/some-crate@1.2.3"
|
|
# - "pkg:npm/%40scope/example@4.5.6"
|
|
|
|
# Pre-cache artifact scanning. When enabled, every artifact is staged into
|
|
# storage and scanned by the configured scanners before it is committed to
|
|
# the cache and served to clients. Scanners never receive artifact bytes
|
|
# directly — each notify call includes a short-lived signed URL that the
|
|
# scanner fetches itself, so the proxy stays agnostic to trivy/ClamAV/Wiz/
|
|
# any custom service. Scanners run concurrently; the first "block" verdict
|
|
# wins and cancels the rest.
|
|
# scanning:
|
|
# enabled: true
|
|
# fail_open: false
|
|
# timeout: 30s
|
|
#
|
|
# # Authenticates pull requests to the internal scan-fetch route.
|
|
# # Required whenever enabled is true. Supports ${VAR_NAME} expansion.
|
|
# signing_key: ${PROXY_SCANNING_SIGNING_KEY}
|
|
#
|
|
# # Address scanners use to reach this proxy to pull staged artifacts.
|
|
# # Defaults to base_url.
|
|
# # fetch_base_url: http://proxy.internal:8080
|
|
#
|
|
# scanners:
|
|
# - name: clamav
|
|
# url: http://clamav-adapter:8080/scan
|
|
# mode: block
|
|
# - name: trivy
|
|
# url: http://trivy-adapter:8081/scan
|
|
# mode: monitor
|
|
# ecosystems: [npm, pypi]
|