Operations

The Operations section is where a deployment's administrators see what the server is doing and change how it runs in the background. Its pages - Metrics, Security posture, Caches and Walks - are for the deployment's administrators. Two pages of each repository belong here too, for anyone with the admin role there: Deploy, once switched on, and Export, which takes a repository's contents out to another repository, as Migrating in and out describes. Beside them this chapter covers what a monitoring system reads over HTTP, webhooks, and the rate limit.

Caches

Caches lists the read caches of the server that renders the page - each one's time to live, how often it answered and how much it holds - and Clear caches on this node empties them. The clear also tells every other server of the deployment to read credentials afresh, so a revoked key another server still remembers stops working there too; the other caches on those servers expire on their own time to live.

Metrics

Metrics lists what every installed module reports about itself: counters, gauges, health checks and the state of each background task, each with its current value and a line saying what it measures. A module that is not installed, or is switched off, reports nothing, so the page shows what this deployment is actually doing - how full the storage quota is, how often the proxy cache answered locally, when the collector last ran.

Security posture

Security posture lists every configuration choice that makes the deployment less safe than it could be, most severe first - running without keys, a gate that admits known malware, no rate limit. Each entry says why it matters and which setting changes it. A clean deployment lists nothing, which is the healthy state, and the count shown in the header is the length of this list.

Observing the posture never changes it: the page is read-only, and it names the setting at fault and the value that fixes it, never a secret the deployment holds. Each entry links here, to its own line of this table:

Advisory Severity Raised when
jenrepo.auth.open critical JENREPO_AUTH=false - every request is served without a key, writes included.
jenrepo.profile.dev critical The dev profile is active, so the console runs its local-only sign-in.
jenrepo.anonymous.write critical anonymous-rights lets a caller without a key write or administer.
jenrepo.gate.malware critical malware-action is ALLOW for a tenant, so a package known to be malicious is admitted.
jenrepo.consistency.config critical One server of several runs with different settings or tenants from the others.
jenrepo.consistency.pointer critical Two servers answer the same path with different content.
jenrepo.anonymous.enabled warning anonymous-rights lets a caller without a key read - right for a public mirror, and worth knowing otherwise.
jenrepo.gate.vulnerability.action warning vulnerability-action is ALLOW for a tenant, so an artifact over the threshold is served.
jenrepo.gate.vulnerability warning vulnerability-threshold is NONE for a tenant, which switches the vulnerability check off.
jenrepo.gate.denylist.action warning deny-list-action is ALLOW for a tenant, so the deny list is ignored.
jenrepo.importer.ssrf warning block-private-import-hosts=false - an import may reach internal addresses, or travel unencrypted.
jenrepo.ratelimit.unset warning rate-limit is 0, so nothing throttles a client.
jenrepo.consistency.stuck warning One server of several has stopped catching up with what the others have seen.
jenrepo.posture.collision warning Two installed modules report under the same advisory name - a packaging fault, shown rather than hidden.

Walks

Some work needs to look at everything the store holds - applying retention, reclaiming space, rebuilding the indexes clients read. The server does it in walks: one pass over the store that every such job rides along on, so the store is read once rather than once per job.

Walks shows the scheduled walks, with when each last ran and what it did. Two are scheduled by default:

Walk When What rides along
retention Daily at 03:00 UTC Applying each repository's retention policy
rebuild Sundays at 03:00 UTC Every job: reclaiming space, repairing indexes, back-filling what a newly installed module needs

Each walk can be edited in place - its schedule as a cron expression with seconds first, in UTC (0 0 3 * * *), whether it is switched on, and which jobs ride along - or removed, and Add a walk schedules another. Walk the store now starts the rebuild walk at once, with the jobs its entry names - every job by default, and every job too when no rebuild walk is scheduled. Like any walk, a rebuild walk naming one job carries that job alone.

A walk reads every object in the store, so on object storage every scheduled walk is a recurring cost. The default schedule keeps the whole-store work weekly; What it costs to run puts numbers on it.

Deploy

Deploy, a page of each repository, publishes a single file from the browser - a one-off artifact that has no build to publish it. Enter the path the artifact is published under, such as /maven/com/example/tool/1.0/tool-1.0.jar, pick the file, and press Publish. It passes the same gate a client's upload does, and it is an admin's to use.

The page is switched off by default; switch it on with JENREPO_DEPLOY=true or under Settings → Modules.

Webhooks

The server can call you back when something happens - a publish, a removal, a hold, a release, a new finding. Webhooks are configured under Settings → Settings, in the Webhooks group:

Setting Meaning
webhook Switches delivery on.
webhook-endpoints One endpoint per line, https://hooks.example.com/repo publish,quarantine - the events after the URL, or none for all.
webhook-secrets Per endpoint, a secret the server signs each delivery with (HMAC-SHA256), as https://hooks.example.com/repo=<secret>.
webhook-attempts How many times a failing delivery is retried, with a growing pause, before it is set aside. Five by default.

Deliveries go out from a background queue, so a slow receiver never slows a publish. An endpoint must be https and on a public address unless webhook-allow-internal permits otherwise.

Rate limits

Every request is metered against a per-tenant ceiling - 6 000 requests a minute by default, a hundred a second - and a request over it is answered 429 with Retry-After: 60. The ceiling is the rate-limit setting: for every tenant under Settings → Settings, or with JENREPO_RATE_LIMIT, and for one tenant on Repositories → Limits. 0 for the deployment removes it.

A request is charged to its key's tenant, and every request without a key shares one bucket of its own. A bucket holds a minute's worth of burst, so a build resolving a large dependency graph in a quick burst gets through while a sustained flood is shed. Health probes and metric scrapes are never limited. Each server of a multi-node deployment keeps its own buckets, so behind a load balancer the effective ceiling is the setting times the number of servers.

When something fails

A failure the server did not mean - a store that cannot be read, a bug - is never answered with its insides. No surface shows an exception, a stack trace, a path on disk or a store key. Each one says that something went wrong and gives a reference, twelve letters and digits, such as 8vjbm05qakwk:

Surface What it shows
API A 500 problem document (application/problem+json) with title and reference
Console The error page, with the reference to quote
jenrepo The refusal, ending Reference: 8vjbm05qakwk
A package client Its own error format, with the same sentence and reference: an OCI error for docker, an npm or Cargo error document, plain text for the rest

The server logs the whole failure under that reference, stack trace included, at ERROR:

ERROR ... Unexpected failure 8vjbm05qakwk while GET /repository/default/releases/...

So a user who reports the reference has told you where to look. /api/logs?q=8vjbm05qakwk finds the line and the request that failed, and the server's own output - docker logs, kubectl logs - holds the stack trace beneath it. A reference is minted per failure, so two reports with one reference are one failure.

A refusal the server did mean - a 404, a 403, a policy verdict - is not a failure. It carries no reference and says why, as it always has.

Endpoints for monitoring

Endpoint Answers Who may read it
/actuator/health, /actuator/health/liveness, /actuator/health/readiness Up or down, for probes Anyone; the detail only to an administrator
/actuator/metrics The server's meters, for a monitoring system A key holding manage:read over *, such as the admin role, of the operator tenant
/api/logs The most recent log entries, filterable by level and text A key holding manage:read over *, of the operator tenant
/api/posture The security posture, as JSON A key holding manage:read over *

/api/logs keeps the last thousand entries in memory, with a sequence number on each, so a script can tail it:

curl -H "Jenesis-Repository-Key: $ADMIN_KEY" \
  'https://repo.example.com/api/logs?level=WARN&limit=50'