Files
tiny-proxy/config.example.yaml
MRLokopandClaude Code d74ad09bf3 List one directory level in the UI instead of walking the whole store
dirBrowse rendered a single directory level but paid for a full
recursive listing of the repo — on CephFS-backed LocalFS that is a
walk of the entire storage root plus a sidecar read per object, which
took Ceph down on large repos. Storage grows a ListDir primitive
(os.ReadDir on localfs, Delimiter on S3) and the UI and the debian
dists fallback use it; the recursive List stays for the docker page
and now starts its walk at the requested prefix.

The per-vrepo storage gauges on /metrics did the same full listing on
every scrape; they are removed — the backend's own accounting (du,
bucket metrics) covers capacity.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-10 09:31:02 +03:00

221 lines
8.3 KiB
YAML

listen: ":8080"
storage:
# localfs | s3 | none. "none" disables caching entirely: every request is
# proxied straight through to the upstream and nothing is stored.
type: localfs
localfs:
root: ./data
# s3:
# bucket: my-cache
# region: us-east-1
# endpoint: http://localhost:9000 # optional, for MinIO etc.
# access_key: minioadmin
# secret_key: minioadmin
# prefix: cache
# GET /metrics serves Prometheus text exposition: per-vrepo request counts,
# durations and cache hit/miss/error counters; per-upstream attempts, response
# statuses, byte totals (payload and real socket bytes) and timings (connect,
# TLS handshake, time-to-first-byte, body); and Go runtime stats. Storage
# sizes are deliberately absent: listing a large store on every scrape is too
# expensive — use the backend's own accounting (`du`, bucket metrics) instead.
# Empty token (the default) leaves the endpoint open; set one to require
# `Authorization: Bearer <token>` or a `?token=<token>` query param.
# metrics:
# token: ""
# Every request is given a trace id (adopted from the caller's X-Request-Id or
# traceparent when it sent one), echoed back in X-Request-Id, attached to every
# log line the request produces, and passed on to the upstreams it calls — so
# one grep follows a request end to end, across chained proxies included.
# log:
# level: info # debug | info | warn | error
# format: text # text | json
# requests: true # one line when a client request arrives and one when it ends
# upstream: true # one line per outbound attempt against an upstream
vrepos:
# docker pull localhost:8080/dockerhub/library/nginx:1.27
- name: dockerhub
type: docker
upstream:
url: https://registry-1.docker.io
# username: myuser # optional Docker Hub credentials
# password: mytoken
# proxy: socks5://127.0.0.1:1080
auth:
mode: public # public | password | users
cache:
manifest_ttl: 5m
# docker pull localhost:8080/ghcr/org/image:tag (authenticated repo example)
- name: ghcr
type: docker
upstream:
url: https://ghcr.io
username: github-user
password: ghp_token
auth:
mode: password # any login + this password
password: s3cret
cache:
manifest_ttl: 1m
# https://localhost:8080/maven/central/com/google/guava/guava/33.0.0-jre/guava-33.0.0-jre.jar
- name: central
type: maven
upstream:
url: https://repo1.maven.org/maven2
auth:
mode: users
users:
alice: pw1
bob: pw2
cache:
metadata_ttl: 5m
# Maven with multiple upstreams (also supported for debian and pacman,
# without filters). Upstreams are tried in order: a 404, 401, 403 or
# connection error falls through to the next
# one, any other status is returned as-is. Each upstream may restrict what it
# serves with allowlist filters:
# groups: wildcard group prefixes; "com.google.*" covers the
# whole com/google tree ('*' crosses dots/slashes)
# artifacts: wildcard artifact names, e.g. "my-lib-*"
# snapshots_only: only -SNAPSHOT paths are requested from it
# An upstream with no filters matches everything. Per-upstream
# credentials and egress proxy work the same as the single-upstream form.
# Any upstream (of any type, single or listed) may set `cache: false` to
# be proxied through without being stored here — see the chained example
# below.
- name: maven-all
type: maven
upstreams:
- url: https://corp.example.com/maven-snapshots
username: deploy
password: s3cret
snapshots_only: true
- url: https://maven.google.com
groups: ["com.google.*"]
- url: https://repo1.maven.org/maven2
# `attempts` covers three failures, each waiting the upstream's
# Retry-After or a backoff when it sends none, at most max_wait per
# wait: a 429 (Too Many Requests), a connection that fails before any
# response arrives, and a transfer that dies mid-body (re-requested
# with a byte range and continued where it stopped). Once the attempts
# are spent the request falls through to the next upstream.
# Defaults: attempts 2, max_wait 5s; attempts 0 disables.
retry:
attempts: 3
max_wait: 10s
auth:
mode: public
cache:
metadata_ttl: 5m
# Chaining: a vrepo may use another vrepo of this proxy as an upstream.
# `cache: false` keeps the aggregator from storing a second copy of what
# the target vrepo already caches — the bytes live in `central` only, and
# `deps` just routes. Reads still hit `deps`'s own cache if something was
# stored there earlier by a cacheable upstream. Chained upstreams are
# ordinary HTTP requests: add username/password if the target vrepo is
# not `auth.mode: public`, and never let a chain loop back on itself.
- name: deps
type: maven
upstreams:
- url: https://mvn.example.com # cached here as usual
- url: http://localhost:8080/maven/central
cache: false # cached in the central vrepo
auth:
mode: public
cache:
metadata_ttl: 5m
# curl -LO http://localhost:8080/github/gh/golang/go/latest.json
# curl -LO http://localhost:8080/github/gh/golang/go/latest/go1.23.0.linux-amd64.tar.gz
- name: gh
type: github
# upstream.url defaults to https://github.com (API: api.github.com).
# For GitHub Enterprise set your instance URL (API: <url>/api/v3).
upstream:
url: https://github.com
# username: github-user # optional; PAT raises API rate limits
# password: ghp_token # and unlocks private repos
auth:
mode: public
# allow restricts which owner/repo pairs may be proxied (path.Match
# globs). Omit or leave empty to allow everything.
allow:
- "golang/*"
- "myorg/mytool"
# redirect: true (default) sends /latest and /snapshot to the resolved
# tag path with a 302; false serves content under the alias URL.
# redirect: false
cache:
metadata_ttl: 5m # release metadata + alias resolution
# Same, but with per-vhost users and an authenticated upstream (private
# repos), serving aliases in place instead of redirecting.
- name: gh-private
type: github
upstream:
url: https://github.com
username: github-user
password: ghp_token
auth:
mode: users
users:
carol: pw3
redirect: false
cache:
metadata_ttl: 1m
# Gitea releases: same URL grammar as the github type under /gitea/.
# There is no default upstream — point url at your instance (its API is
# served at <url>/api/v1).
# curl -LO http://localhost:8080/gitea/gt/myorg/mytool/latest/mytool_linux-amd64
- name: gt
type: gitea
upstream:
url: https://gitea.example.com
# username: gitea-user # optional; token unlocks private repos
# password: gitea_token
auth:
mode: public
# allow: ["myorg/*"]
# redirect: false
cache:
metadata_ttl: 5m
# Debian / APT repo. apt sources.list: deb http://localhost:8080/debian/deb bookworm main
# Open /ui/debian/deb/ for a generated sources.list line per distro version
# (bookworm, trixie, noble, ...) with each suite's components and
# architectures, probed from the mirror and memoized for metadata_ttl.
# Metadata under dists/** (Release, InRelease, Packages.*, ...) is cached
# for metadata_ttl; pool/** and by-hash/** are content-addressed and
# cached forever. Multiple upstreams act as mirrors: a 404, 401, 403 or
# connection error falls through to the next one (they must serve the
# same archive layout).
- name: deb
type: debian
upstreams:
- url: https://deb.debian.org/debian
- url: http://ftp.us.debian.org/debian
auth:
mode: public
cache:
metadata_ttl: 5m # dists/** freshness; packages immutable
# Pacman (Arch) mirror. pacman.conf: Server = http://localhost:8080/pacman/arch/$repo/os/$arch
# <repo>.db / <repo>.files (any compression, plus .sig) and lastupdate
# are cached for metadata_ttl; *.pkg.tar.* packages are immutable.
- name: arch
type: pacman
upstream:
url: https://geo.mirror.pkgbuild.com
auth:
mode: public # pacman has no native HTTP-auth support
cache:
metadata_ttl: 5m