| description | Every pypiron flag, PYPIRON_ environment variable, and pypiron.toml setting for running a self-hosted PyPI server, with defaults and precedence. |
|---|
Configure pypiron with flags, PYPIRON_* environment variables, or
pypiron.toml.
Precedence: CLI > environment > file > defaults.
| Flag | Env | Default | Meaning |
|---|---|---|---|
--config PATH |
PYPIRON_CONFIG |
./pypiron.toml when present |
Config file. Read by every command. |
--log-format text|json |
PYPIRON_LOG_FORMAT |
text |
Human logs or one JSON object per line. |
pypiron config init > pypiron.tomlThe generated file is fully commented. A small real config looks like this:
private-prefix = "acme"
[serve]
bind-addr = "0.0.0.0:8080"
buckets = ["s3://acme-pypiron@us-east-1"]
proxy-upstream = "https://pypi.org"
[mirror]
exclude-newer = "7 days"
include-format = ["wheel"]
[sync]
to = "http://localhost:8080"Sections:
| Section | Owns |
|---|---|
| top level | private-prefix |
[serve] |
server, proxy, storage, counters, logs |
[mirror] |
package and file selection shared by proxy and sync |
[sync] |
destination and sync worker settings |
Serve secrets stay in CLI/env. sync.admin-pass exists for closed deployment
files, but env is cleaner: PYPIRON_SYNC_ADMIN_PASS.
Disk is the default. Use --buckets for S3, GCS, Azure, or compatible object
storage. Buckets must already exist.
| Flag | Env | Default | Meaning |
|---|---|---|---|
--buckets URI,... |
PYPIRON_BUCKETS |
none (disk) | One or more bucket URIs, any mix of backends, in preference order. Unset means disk. |
--data-dir PATH |
PYPIRON_DATA_DIR |
~/.pypiron/packages |
Disk root. Ignored when --buckets is set. |
--storage-prefix PREFIX |
PYPIRON_STORAGE_PREFIX |
none | Keep everything under one subtree, so pypiron can share a bucket. |
pypiron serve --buckets s3://acme-pypiron
Credentials come from the backend's native chain. The file form is:
[serve]
buckets = ["s3://acme-pypiron"]Each URI has a scheme and may include @region:
s3://nameors3://name@region— S3 bucket.gs://nameorgs://name@region— GCS bucket.az://containeroraz://container@region— Azure blob container.
On S3, @region selects the signing region. With several buckets, it also
selects the nearest read bucket.
Half-configured credentials make startup fail.
- S3 — the standard AWS chain: env vars, web identity, instance role, task role.
- GCS — a service-account key (
--gcs-service-account-path) enables presigned redirects; without one, pypiron uses Application Default Credentials and downloads stream through the node. - Azure — the account access key (
--azure-access-key) enables presigned (SAS) redirects.
These apply to every bucket of the same backend:
| Flag | Env | Default | Meaning |
|---|---|---|---|
--s3-endpoint-url URL |
PYPIRON_S3_ENDPOINT_URL |
none | S3-compatible endpoint (MinIO et al.); every s3:// bucket. |
--s3-force-path-style |
PYPIRON_S3_FORCE_PATH_STYLE |
false |
Path-style addressing; every s3:// bucket. |
--gcs-service-account-path PATH |
PYPIRON_GCS_SERVICE_ACCOUNT_PATH |
none | GCS service-account JSON key. Enables presigned redirects. |
--gcs-endpoint-url URL |
PYPIRON_GCS_ENDPOINT_URL |
none | GCS local emulator or custom endpoint. |
--azure-account NAME |
PYPIRON_AZURE_ACCOUNT |
none | Azure storage account. |
--azure-access-key KEY |
PYPIRON_AZURE_ACCESS_KEY |
none | Azure account key; enables signed (SAS) URLs. CLI/env only, never in the file. |
--azure-endpoint-url URL |
PYPIRON_AZURE_ENDPOINT_URL |
none | Azurite or custom endpoint. |
--azure-use-emulator |
PYPIRON_AZURE_USE_EMULATOR |
false |
Use Azurite defaults. |
Use [serve.bucket."URI"] when buckets need different endpoints or
credentials. These overrides are TOML-only.
[serve]
buckets = ["s3://iron-east@us-east-1", "s3://minio-cache"]
[serve.bucket."s3://minio-cache"]
endpoint-url = "http://minio.internal:9000"
force-path-style = true
env-prefix = "MINIO_CACHE_" # reads MINIO_CACHE_AWS_ACCESS_KEY_ID / ..._AWS_SECRET_ACCESS_KEYThe key matches scheme://name; any @region is ignored.
| Field | Schemes | Meaning |
|---|---|---|
endpoint-url |
any | Endpoint for this bucket, overriding the backend-wide flag. An http:// value allows plaintext. |
force-path-style |
s3 | Path-style addressing for this bucket. |
env-prefix |
s3, azure | Names the env vars holding this bucket's credentials (below). |
service-account-path |
gcs | Service-account JSON key for this bucket. Also enables presigned redirects for it. |
account |
azure | Storage account for this bucket. |
env-prefix names environment variables; it does not store a secret:
- S3 —
<PREFIX>AWS_ACCESS_KEY_ID,<PREFIX>AWS_SECRET_ACCESS_KEY, and optional<PREFIX>AWS_SESSION_TOKEN. - Azure —
<PREFIX>AZURE_ACCESS_KEY. - GCS has no
env-prefix: its credential is a key file, so useservice-account-pathinstead.
pypiron refuses startup when:
- An override keyed to a bucket not in
--bucketsfails, listing the valid buckets (typo protection). - An
env-prefixwith only one credential half set — or neither — fails: a scoped credential was promised and isn't fully there. - A field used on the wrong scheme fails, naming the field and bucket.
--storage-prefix pypi keeps all keys under pypi/. This lets pypiron share a
bucket and lets separate servers use different prefixes. On disk, it creates a
subdirectory under --data-dir. Choose the prefix before loading packages;
changing it points the server at a different, initially empty key space.
| Flag | Env | Default | Meaning |
|---|---|---|---|
--buckets URI,... |
PYPIRON_BUCKETS |
none | Bucket URIs in preference order, any mix of backends. Enables cross-region and cross-cloud replication and failover. |
Give every node the same ordered bucket list. The first bucket is preferred:
pypiron serve --buckets s3://iron-east@us-east-1,s3://iron-west@us-west-2
PYPIRON_BUCKETS=s3://iron-east@us-east-1,s3://iron-west@us-west-2
@region keeps reads local; on S3 it also selects the signing region. Mixed
backends are supported. With more than one bucket:
- Private uploads, synced packages, and proxy-cached packages replicate to every bucket. Budget the stored corpus once per bucket.
- An upload waits for every healthy bucket. A failed bucket catches up from a
repair record after it recovers. If pypiron cannot save that record, it
returns
503. - Compatible buckets use their provider's server-side copy operation. Other
pairs stream through the node. Startup logs
transport=copyortransport=streamfor each pair. - Keep encryption modes consistent to preserve server-side copy. Mixed modes fall back to verified streaming.
- Deleting a proxy-cached or synced file returns
409; distributed cache eviction is not supported.
Multi-region deployment and recovery
| Flag | Env | Default | Meaning |
|---|---|---|---|
--bind-addr ADDR |
PYPIRON_BIND_ADDR |
0.0.0.0:8080 |
Listen address. |
--admin-user USER |
PYPIRON_ADMIN_USER |
admin |
Admin username. |
--admin-pass PASS |
PYPIRON_ADMIN_PASS |
none | Enables publish, mirror, delete, yank. |
--uploader-user USER |
PYPIRON_UPLOADER_USER |
none | Upload-only username. |
--uploader-pass PASS |
PYPIRON_UPLOADER_PASS |
none | Upload-only password. |
--read-user USER |
PYPIRON_READ_USER |
none | Optional read username. |
--read-pass PASS |
PYPIRON_READ_PASS |
none | Optional read password. |
--private-prefix PREFIX |
PYPIRON_PRIVATE_PREFIX |
none | Reserve PREFIX and PREFIX-* for private packages. |
--proxy-upstream URL |
PYPIRON_PROXY_UPSTREAM |
none | On-demand mirror source, usually https://pypi.org. |
--allow-insecure-upstream |
PYPIRON_ALLOW_INSECURE_UPSTREAM |
false |
Permit a plaintext http:// proxy upstream. This exposes both bytes and their claimed hash to interception. |
--proxy-stream-threshold SIZE |
PYPIRON_PROXY_STREAM_THRESHOLD |
16MiB |
Stream an uncached file at or above this size while fetching it. The last 64KiB waits for hash verification. Accepts 64MB, 1GiB, etc.; minimum 64KiB; off buffers every file. |
--proxy-allow-host HOST |
PYPIRON_PROXY_ALLOW_HOST |
none | Permit the proxy to fetch listing-derived URLs (artifact, .metadata, .provenance, redirect targets) whose host matches HOST exactly, even if it resolves to a private address. Repeatable; comma-separated in the env var. Only the configured upstream host is exempt otherwise. |
--proxy-allow-cidr CIDR |
PYPIRON_PROXY_ALLOW_CIDR |
none | Like --proxy-allow-host, but permits any target IP inside CIDR (e.g. 10.0.0.0/8). Repeatable; comma-separated in the env var. |
--upstream-ca-cert PEM |
PYPIRON_UPSTREAM_CA_CERT |
none | Extra CA certificates for proxy, sync-source, and advisory TLS. Adds to built-in roots. A missing or invalid bundle refuses startup. Proxy setup. |
--advisory-feed URL|PATH |
PYPIRON_ADVISORY_FEED |
OSV PyPI export | Feed for malware blocking and the org audit: a URL or local path to the OSV PyPI advisory export. Defaults to https://osv-vulnerabilities.storage.googleapis.com/PyPI/all.zip (named in the startup log); a URL fetch honors HTTP(S)_PROXY. "" disables both features. |
--malware-block true|false |
PYPIRON_MALWARE_BLOCK |
true |
Refuse public files named by OSV MAL-* advisories. The binary includes a first-boot block set; a live or synced snapshot replaces it. Explicit true requires a live snapshot at startup. Does not control PEP 792 quarantine. |
--malware-probe-secs N |
PYPIRON_MALWARE_PROBE_SECS |
120 |
Check OSV for new malware between daily snapshots. 0 disables. Requires malware blocking and the standard OSV all.zip feed. |
--metrics-project-labels |
PYPIRON_METRICS_PROJECT_LABELS |
false |
Attach per-client project labels to /metrics. Off by default: /metrics is unauthenticated and the label derives from the username tag, so exposing it lets any scraper list internal project names. |
--spool-dir PATH |
PYPIRON_SPOOL_DIR |
system temp | Upload/proxy spool directory. |
--artifact-delivery auto|redirect|stream |
PYPIRON_ARTIFACT_DELIVERY |
auto |
Redirect object-store downloads for compatible clients or stream through the server. A first uncached proxy download may stream under --proxy-stream-threshold. |
--wait-on-upload |
PYPIRON_WAIT_ON_UPLOAD |
false |
Wait for index visibility before upload returns. |
--wait-on-upload-secs N |
PYPIRON_WAIT_ON_UPLOAD_SECS |
10 |
Bound for that wait. |
--max-concurrent-artifact-writes N |
PYPIRON_MAX_CONCURRENT_ARTIFACT_WRITES |
4 |
Concurrent object-store uploads allowed to buffer up to 64MiB each. Default worst case is about 256MiB. Disk is not gated; 0 is unlimited. |
--allow-legacy-versions |
PYPIRON_ALLOW_LEGACY_VERSIONS |
false |
Accept direct uploads with non-PEP-440 versions. File type is irrelevant. Sync has a separate flag below. |
--access-log |
PYPIRON_ACCESS_LOG |
false |
Log reads too, not only mutations. |
--access-log-format structured|clf |
PYPIRON_ACCESS_LOG_FORMAT |
structured |
Structured logs or Combined Log Format. |
--trusted-proxy |
PYPIRON_TRUSTED_PROXY |
false |
Honor X-Forwarded-For/X-Real-IP. Enable only behind a proxy that replaces these headers; otherwise callers can forge their logged address. Login throttling. |
--login-cooldown-secs N |
PYPIRON_LOGIN_COOLDOWN_SECS |
300 |
Lock one address for this long after five failed logins; returns 429 with Retry-After. Per instance; IPv6 groups by /64; 0 disables. |
--worker-interval-secs N |
PYPIRON_WORKER_INTERVAL_SECS |
1 |
Index, replication, and bucket-health poll cadence. |
--bucket-leave-failures N |
PYPIRON_BUCKET_LEAVE_FAILURES |
3 |
Consecutive timeout (including 408), connection, or 5xx failures before selecting the next bucket. |
--bucket-return-healthy-secs N |
PYPIRON_BUCKET_RETURN_HEALTHY_SECS |
300 |
Healthy time required before returning to a preferred bucket. Startup warns when this may be shorter than catch-up confirmation. |
--node-region LABEL |
PYPIRON_NODE_REGION |
detected | This node's region, matched against bucket @region labels to choose the bucket it reads from. Cloud nodes detect it automatically (AWS/GCP/Azure); set it for on-prem or MinIO. Steers reads only, never writes. Multi-bucket only. |
--fanout-grace-secs N |
PYPIRON_FANOUT_GRACE_SECS |
30 |
Grace a lagging secondary bucket gets on upload before pypiron records a repair and returns. One slow bucket adds at most this to a publish. Multi-bucket only. |
--repl-sweep-interval-secs N |
PYPIRON_REPL_SWEEP_INTERVAL_SECS |
300 |
Backstop interval for draining pending cross-bucket repairs. Repairs also drain the moment a bucket recovers. Multi-bucket only. |
--intent-grace-secs N |
PYPIRON_INTENT_GRACE_SECS |
900 |
Grace for an upload or cross-bucket package operation. Minimum 3; maximum 9223372036854775807. |
--audit-on-boot true|false |
PYPIRON_AUDIT_ON_BOOT |
true |
Run the consistency check on boot: indexes against stored files, buckets against each other. |
--reconcile-interval-secs N |
PYPIRON_RECONCILE_INTERVAL_SECS |
86400 |
How often that check repeats. |
--quarantine-poll-secs N |
PYPIRON_QUARANTINE_POLL_SECS |
30 |
Maximum delay before other nodes adopt a project freeze. The receiving node refuses immediately. One small listing per node per interval. |
--transparency true|false |
PYPIRON_TRANSPARENCY |
true |
Record each audit's file hashes under _transparency/; pypiron verify-chain reads the records. Off stops new records only. |
--lease-ttl-secs N |
PYPIRON_LEASE_TTL_SECS |
30 |
Multi-node leader lease TTL. |
--download-stats true|false |
PYPIRON_DOWNLOAD_STATS |
true |
Count package downloads. |
--counters-resolution DUR |
PYPIRON_COUNTERS_RESOLUTION |
1d |
Counter bucket width: 1d, 1h, 30m, 2h, etc. |
--counters-flush-interval-secs N |
PYPIRON_COUNTERS_FLUSH_INTERVAL_SECS |
300 |
Counter flush cadence. |
--counters-rollup-interval-secs N |
PYPIRON_COUNTERS_ROLLUP_INTERVAL_SECS |
3600 |
Finished-day compaction cadence. |
--counters-retention-days N |
PYPIRON_COUNTERS_RETENTION_DAYS |
90 |
Counter retention. |
--index-cache-ttl-secs N |
PYPIRON_INDEX_CACHE_TTL_SECS |
1 |
Staleness bound on the in-memory index/page caches. Only matters multi-node — a node's own writes invalidate its caches exactly; the TTL bounds how long another node's write can go unseen. Single-node deployments can raise it freely. |
--token-signing-key KEY |
PYPIRON_TOKEN_SIGNING_KEY |
none | Enables 5-minute install tokens. |
No write credential means read-only. No read credential means installs are open to the network. Half-configured credentials refuse startup.
Username tags are for attribution: reader+billing-api authenticates as
reader and records billing-api in request metrics. Tags are capped and
restricted to [A-Za-z0-9._-].
pypiron_storage_ops_total reports backend reads, writes, lists, and deletes.
With the advisory feed enabled, use
pypiron_advisory_snapshot_age_seconds,
pypiron_advisory_last_refresh_age_seconds, and
pypiron_malware_probe_age_seconds to alert on stale data or failed polling.
pypiron_blocked_downloads_total counts refused malware downloads.
Sync, proxy fetches, and advisory polling honor HTTPS_PROXY, HTTP_PROXY,
ALL_PROXY, and NO_PROXY. Cloud instance-metadata detection always uses its
link-local address directly.
Use --upstream-ca-cert when the proxy re-signs TLS with a private CA. The
bundle adds to the built-in roots and must parse at startup.
pypiron still rejects forbidden non-routable destinations in their IPv4, IPv6, and NAT64 forms. Public IPv6 addresses are allowed. The forward proxy resolves hostnames, so its egress policy must enforce hostname restrictions.
serve --proxy-upstream and pypiron sync share [mirror].
| TOML key | Flag | Env |
|---|---|---|
include-packages |
--include-package SPEC |
PYPIRON_INCLUDE_PACKAGE |
include-packages-from |
--include-packages-from FILE |
PYPIRON_INCLUDE_PACKAGES_FROM |
exclude-packages |
--exclude-package SPEC |
PYPIRON_EXCLUDE_PACKAGE |
exclude-packages-from |
--exclude-packages-from FILE |
PYPIRON_EXCLUDE_PACKAGES_FROM |
include-format |
--include-format VALUE |
PYPIRON_INCLUDE_FORMAT |
include-python-tag |
--include-python-tag TAG |
PYPIRON_INCLUDE_PYTHON_TAG |
include-abi-tag |
--include-abi-tag TAG |
PYPIRON_INCLUDE_ABI_TAG |
include-platform-tag |
--include-platform-tag TAG |
PYPIRON_INCLUDE_PLATFORM_TAG |
exclude-python-tag |
--exclude-python-tag TAG |
PYPIRON_EXCLUDE_PYTHON_TAG |
exclude-abi-tag |
--exclude-abi-tag TAG |
PYPIRON_EXCLUDE_ABI_TAG |
exclude-platform-tag |
--exclude-platform-tag TAG |
PYPIRON_EXCLUDE_PLATFORM_TAG |
exclude-python-below |
--exclude-python-below X.Y |
PYPIRON_EXCLUDE_PYTHON_BELOW |
exclude-larger |
--exclude-larger SIZE |
PYPIRON_EXCLUDE_LARGER |
exclude-newer |
--exclude-newer WHEN |
PYPIRON_EXCLUDE_NEWER |
exclude-older |
--exclude-older WHEN |
PYPIRON_EXCLUDE_OLDER |
exclude-dev |
--exclude-dev |
PYPIRON_EXCLUDE_DEV |
exclude-windows |
--exclude-windows |
PYPIRON_EXCLUDE_WINDOWS |
exclude-prereleases |
--exclude-prereleases |
PYPIRON_EXCLUDE_PRERELEASES |
include-yanked |
--include-yanked |
PYPIRON_INCLUDE_YANKED |
Rules:
- Package specs are names with optional PEP 440 specifiers:
requests,six==1.16.0,requests>=2.20,<3. syncnormally requires an include list. A pypicloud private migration may use--private-patternor--private-patterns-fromas its work list instead. Proxy without an include list is open for any non-private package.- Omit a list to leave that filter unset. An explicit empty list or environment value is refused because it could erase a stricter value from another config layer.
- Excludes win.
include-formatacceptswheel,sdist, andother.- Tag filters match wheel tags and support
*. exclude-platform-tag = ["win*", "macosx_*"]is the usual Linux CI filter.exclude-python-below = "3.9"drops wheels built only for older Pythons but keeps sdists,py3, andabi3.exclude-newersets the dependency cooldown; defaults to7, a sliding 7-day hold.""disables it.WHENaccepts an RFC 3339 timestamp, bare date, bare day count, friendly duration ("30 days"), or ISO 8601 duration (P30D).- Yanked files are not fetched unless
include-yanked = true. Files already cached remain listed as yanked so pinned installs work.
exclude-packages removes matching names or versions from package listings,
including content already cached. It takes effect after restart. Stored bytes
remain available by direct file URL until an admin deletes them; mirrored-file
deletion is refused with multiple buckets.
Other content filters control future fetches. They do not purge files already stored.
sync mirrors over HTTP into a running pypiron server. It never writes storage
directly.
The pypicloud-specific source and private-pattern options require a build newer
than 0.0.17. Use the next release when available, or run
cargo run --locked -- sync ... from a source checkout.
| Flag | Env | Default | Meaning |
|---|---|---|---|
--from URL |
PYPIRON_SYNC_FROM |
https://pypi.org |
Source index. Name a Simple endpoint in full when it lives off /simple (devpi: .../<user>/<index>/+simple). With --source-kind pypicloud, use the pypicloud application root instead. |
--source-kind simple|pypicloud |
PYPIRON_SOURCE_KIND |
simple |
Source protocol. pypicloud reads /api/package/, requires --as-private, and supports private-name patterns. Also [sync].source-kind. |
--source-user USER |
PYPIRON_SYNC_SOURCE_USER |
none | Authenticated-source username. Sent only to the same scheme, host, and port. Requires --source-pass; also [sync].source-user. |
--source-pass PASS |
PYPIRON_SYNC_SOURCE_PASS |
none | Password for an authenticated source. Requires --source-user; also [sync].source-pass. |
--allow-insecure-source |
PYPIRON_ALLOW_INSECURE_SOURCE |
false |
Send source credentials over plaintext HTTP. Unauthenticated HTTP sources need no flag. |
--upstream-ca-cert PEM |
PYPIRON_UPSTREAM_CA_CERT |
none | Extra CA certificates for source TLS. Adds to built-in roots and must parse at startup. Proxy setup. |
--to URL |
PYPIRON_SYNC_TO |
required | Destination pypiron URL. |
--admin-user USER |
PYPIRON_SYNC_ADMIN_USER |
none | Destination admin user. |
--admin-pass PASS |
PYPIRON_SYNC_ADMIN_PASS |
none | Destination admin password. |
--private-prefix PREFIX |
PYPIRON_PRIVATE_PREFIX |
none | Refuse to mirror private names. |
--as-private |
PYPIRON_SYNC_AS_PRIVATE |
false |
Import as private packages. Uses the migration time and does not preserve yank state. Public-owned names require emptying and origin release. Migration guide. |
--private-pattern PATTERN |
PYPIRON_PRIVATE_PATTERN |
none | Declare pypicloud project names private. Repeatable; matches the entire PEP 503-normalized name and supports only *. A bare * is refused. Valid only with --source-kind pypicloud --as-private; also [sync].private-patterns. |
--private-patterns-from FILE |
PYPIRON_PRIVATE_PATTERNS_FROM |
none | Read pypicloud private-name patterns from a file, one per line. Blank lines and # comments are ignored; also [sync].private-patterns-from. |
--advisory-feed URL|PATH |
PYPIRON_ADVISORY_FEED |
relay from --from |
Deliver an advisory snapshot to the destination. A URL or path overrides the source feed; "" disables. Failure warns but does not stop package sync. Also [sync].advisory-feed. |
--concurrency N |
PYPIRON_SYNC_CONCURRENCY |
4 |
Transfers within one package. |
--package-concurrency N |
PYPIRON_SYNC_PACKAGE_CONCURRENCY |
8 |
Packages in parallel. |
--spool-dir PATH |
PYPIRON_SYNC_SPOOL_DIR |
system temp | Download spool directory. |
--dry-run |
PYPIRON_SYNC_DRY_RUN |
false |
Print work, write nothing. |
--full |
PYPIRON_SYNC_FULL |
false |
Ignore cursors and reconcile every selected project. |
--no-progress |
PYPIRON_SYNC_NO_PROGRESS |
false |
Hide the live progress meter. |
--allow-legacy-versions |
PYPIRON_ALLOW_LEGACY_VERSIONS |
false |
Mirror files without an inferable PEP 440 version. Otherwise they are logged and skipped. Applies in sync, because the destination accepts mirror uploads. Also [sync].allow-legacy-versions. |
Re-running sync is normal. Existing files stay; yanks, removals, and project status reconcile from upstream.
Enable with --token-signing-key. Mint with:
export UV_INDEX_COMPANY_USERNAME=__token__
export UV_INDEX_COMPANY_PASSWORD=$(
pypiron create-token --url http://pypiron:8080 --auth reader:secret
)| Flag | Env | Default | Meaning |
|---|---|---|---|
--url URL |
PYPIRON_URL |
required | Server URL. |
--role reader|uploader|admin |
none | reader |
Requested role. |
--auth user:pass |
PYPIRON_AUTH |
none | Credential used to mint the token. |
--repo VALUE |
none | git remote | Attribution override. |
--commit VALUE |
none | git commit | Attribution override. |
--user VALUE |
none | local user | Attribution override. |
Tokens live for 5 minutes and cannot outrank the credential that minted them.
| Command | Use |
|---|---|
pypiron healthcheck |
Probe /health; --url / PYPIRON_HEALTHCHECK_URL overrides the target. |
pypiron verify-index |
Read-only full index check against the selected storage backend. --deep re-hashes every stored file too. |
pypiron rebuild-index |
Rebuild every index from stored files. |
pypiron buckets migrate |
Apply a changed --buckets list across every reachable bucket. |
pypiron origin release PACKAGE |
Release an empty package name for deliberate private/public repurposing — the only way to flip a mirror-owned name to private; there is no in-place reclaim. Every configured bucket must be reachable and empty for that package. |
Maintenance commands use the same storage flags and [serve] configuration as
the server.
verify-index compares indexes with stored files and checks recorded sizes.
--deep also hashes every artifact, which reads the full corpus. Mismatches exit
1.
verify-chain checks the _transparency/ records against storage. Changed or
missing content exits 1. A filename recorded under two hashes is reported as
fingerprint-changed but is non-fatal because a deliberate public-to-private
replacement has the same shape. --strict makes it fatal. Preventing rollback
of the log itself requires Object Lock in COMPLIANCE mode.
buckets migrate refuses to drop the only copy of a file or run while repairs
are pending. Add the replacement, wait for replication, then remove the old
bucket. --force can discard content permanently.
| Flag | Env | Default | Use |
|---|---|---|---|
--force |
PYPIRON_MIGRATE_FORCE |
false |
On buckets migrate, drop a bucket even when it holds the fleet's only copy of some content. Permanent data loss — back the corpus up onto a surviving bucket first. |
--deep |
PYPIRON_VERIFY_DEEP |
false |
On verify-index, re-hash every stored file against the SHA-256 its record publishes. Reads the whole corpus once. |
--strict |
PYPIRON_VERIFY_CHAIN_STRICT |
false |
On verify-chain, treat any fingerprint-changed result as a failure. |
Stop writes before origin release. It refuses a package with any stored file
except .origin, or with pending write/replication work, and conditionally
releases the claim on each configured bucket.
These series appear only when you configure two or more buckets:
| Metric | Meaning |
|---|---|
pypiron_replication_objects_total |
Artifact records copied into another bucket. |
pypiron_replication_bytes_total |
Artifact bytes copied into other buckets; companion metadata is not included. |
pypiron_replication_freezes_total |
Same-name, different-byte upload collisions where the loser was quarantined (or both quarantined when the arrival order was too close to call). Needs a human. Any increase needs attention. |
pypiron_replication_marker_backlog{dest} |
Pending cross-bucket repairs (fan-out failures awaiting drain) found on reachable source buckets. During a source outage this is a lower bound. |
pypiron_reconcile_diff_duration_seconds |
Wall time of the last pairwise full comparison. |
pypiron_bucket_health_state{bucket,index} |
Per-node view: healthy 1, unknown 0, unhealthy -1. |
pypiron_bucket_selected{bucket,index} |
Per-node selected bucket for writes: selected 1, all others 0. |
pypiron_bucket_read_selected{bucket,index} |
Per-node bucket serving reads: the region bucket while it is healthy and caught up, otherwise the same as pypiron_bucket_selected. |
pypiron_bucket_health_alarms_total{bucket,index} |
Storage errors that do not prove an outage, including credentials, permissions, CAS, KMS, quota, and configuration. |
pypiron_bucket_selection_generation |
Number that changes when this node selects another bucket. |
pypiron_bucket_topology_write_fenced |
1 when a runtime topology mismatch has stopped mutations; reads remain available. |
Alert on any freeze, a non-zero topology fence, persistent health alarms, or a backlog that keeps growing after its destination recovers. The backlog counts pending repairs, not bytes.
| Endpoint | Auth | Meaning |
|---|---|---|
/simple/ |
read | Package index. |
/files/<pkg>/<file> |
read | Artifact bytes. |
/legacy/ |
uploader/admin | Upload API. |
/health |
open | Liveness: the process is up. Always 200 while serving (a Kubernetes livenessProbe). |
/ready |
open | Readiness: this node can serve reads. Point your load balancer and a Kubernetes readinessProbe here. |
/metrics |
open | Prometheus metrics. |
/stats/downloads |
read | Global download stats. |
/stats/downloads/<pkg> |
read | Per-package download stats. |
/audit |
admin | Org audit: hosted packages a known advisory affects, ranked by downloads over the last 30 days (HTML). |
/audit.json |
admin | The same audit report as JSON. |
/advisories/feed |
read (GET), admin (PUT) | Advisory snapshot: readers pull it (etag-conditioned); an admin pushes a delivered one. |
/tokens |
read/uploader/admin, or open reader token | Mint install tokens. |
/files/.../yank |
admin | Yank a file. |
DELETE /files/<pkg>/<file> |
admin | Delete a file. Refused for mirrored files — anything that came from an upstream, cached on demand or pulled by sync — when you run more than one bucket. |
/project/<pkg>/status |
admin | Set project status. |