aquasecurity/trivy
Server
Active contributors: knqyf263, simar7, DmitriyLewen
Purpose
trivy server runs Trivy as a long-lived RPC server that holds the vulnerability database and the cache, and serves scan requests from trivy client (or any of the regular subcommands launched with --server <url>). Splitting the work this way moves the multi-gigabyte DB and the warm cache out of every CI runner and into a single managed service.
Directory layout
pkg/
├── commands/
│ └── server/
│ └── run.go # entrypoint for `trivy server`
└── rpc/
├── client/
│ ├── client.go # remote.Service implementation of scan.Backend
│ └── headers.go # auth and trace headers
└── server/
├── server.go # server wiring
└── listen.go # HTTP listener + middleware
rpc/
├── scanner/ # Twirp service definition + generated code
├── cache/ # cache RPC for blob upload
└── common/ # shared typesKey abstractions
| Symbol | File | Purpose |
|---|---|---|
Run |
pkg/commands/server/run.go |
Builds the server config and starts the listener. |
server.NewServer |
pkg/rpc/server/server.go |
Wires the scan service, cache service, and Twirp handlers. |
server.Listen |
pkg/rpc/server/listen.go |
HTTP listener with auth, gzip, and timeout middleware. |
client.NewClient |
pkg/rpc/client/client.go |
Returns a Twirp client and adapts it to scan.Backend. |
rpc.Convert* |
pkg/rpc/convert.go |
Converts between in-process types and protobuf-generated types. |
Scanner Twirp service |
rpc/scanner/service.proto |
Wire protocol for scan requests. |
Cache Twirp service |
rpc/cache/service.proto |
Wire protocol for blob upload. |
How a client/server scan works
sequenceDiagram
participant CLI as trivy client / trivy image --server
participant Artifact as artifact.Artifact (client side)
participant Cache as cache.RemoteCache
participant Server as trivy server
participant LocalScan as local.Service (server side)
participant DB as Trivy DB
CLI->>Artifact: Inspect(ctx)
Artifact->>Cache: PutArtifact(...) / PutBlob(...)
Cache->>Server: Twirp Cache.PutBlob
Server->>Server: write blob to cache
CLI->>Server: Twirp Scanner.Scan(artifactID, blobIDs, options)
Server->>LocalScan: Scan(...)
LocalScan->>DB: query vulnerabilities
LocalScan-->>Server: ScanResponse
Server-->>CLI: ScanResponse
CLI->>CLI: write reportThe two RPC services are deliberately split:
Cache— used during artifact inspection to upload analysis blobs from the client to the server's cache. Defined inrpc/cache/service.proto.Scanner— used after inspection to ask the server to scan the uploaded artifact. Defined inrpc/scanner/service.proto.
Because blob keys are content digests, repeated scans of the same image across many clients reuse blobs that another client uploaded earlier, similar to how Docker registries deduplicate layers.
Server lifecycle
Run in pkg/commands/server/run.go does the following:
- Validate the configuration (listen address, cache backend, DB repository, etc.).
- Initialize the cache backend (filesystem, Redis, or remote — see cache).
- Initialize the Trivy DB (
pkg/db/db.go). - Build the local scanner backend (
pkg/scan/local.NewService). - Start the Twirp HTTP listener (
pkg/rpc/server/listen.go). - Periodically refresh the DB based on
--db-refresh-interval.
The server speaks Twirp over plain HTTP by default; TLS is supported via --listen-tls or by fronting it with a reverse proxy.
Authentication
The server supports a simple shared-secret token via the --token flag and the Trivy-Token header. Clients pass --token (or set TRIVY_TOKEN). The header check is in pkg/rpc/client/headers.go and pkg/rpc/server/listen.go. For real production deployments, an mTLS or sidecar-auth setup is more typical.
Configuration
The server is configured by the RemoteFlagGroup on the client side (pkg/flag/remote_flags.go) and a server-side flag composition on trivy server (pkg/commands/app.go's NewServerCommand). Notable flags:
--listen— listen address (defaultlocalhost:4954).--listen-tls,--cert-file,--key-file— TLS termination.--token,--token-header— shared-secret auth.--cache-backend— backing store (fs,redis,memory).--db-repository— override the Trivy DB OCI image.--db-refresh-interval— how often to re-check for DB updates.
Wire-format compatibility
Trivy treats .proto files as the canonical contract. When changing the wire format:
- Update the
.protofile underrpc/<service>/. - Regenerate via
buf generate(ormage build:rpc). - Update
pkg/rpc/convert.goto round-trip the new field. - Ensure backward compatibility — older clients should still work against newer servers and vice versa.
Integration points
- Cache — the server typically uses
--cache-backend redisfor shared multi-replica caches. - Trivy DB — the server is the natural home for the DB; clients can scan without it.
- VEX — VEX filtering happens on the client side after the server returns the report.
Entry points for modification
- Add a new RPC method — extend
rpc/scanner/service.proto, regenerate, then add a server handler inpkg/rpc/server/and a client wrapper inpkg/rpc/client/. - Change auth — modify
pkg/rpc/server/listen.gofor the server side,pkg/rpc/client/headers.gofor the client side, andpkg/flag/remote_flags.gofor new flags. - Add observability — the listener middleware in
listen.gois the natural place for metrics, tracing, and structured request logs.
Key source files
| File | Purpose |
|---|---|
pkg/commands/server/run.go |
trivy server command implementation. |
pkg/rpc/server/server.go |
Wiring: cache, scanner, Twirp registration. |
pkg/rpc/server/listen.go |
HTTP listener + middleware. |
pkg/rpc/client/client.go |
Client-side adapter to scan.Backend. |
pkg/rpc/client/headers.go |
Auth and tracing headers. |
pkg/rpc/convert.go |
Between-format conversions. |
rpc/scanner/service.proto |
Scanner service definition. |
rpc/cache/service.proto |
Cache service definition. |
pkg/flag/remote_flags.go |
Client-side --server/--token flags. |
See also
- RPC system — deeper look at the wire protocol and code generation.
- Cache system — backends used by the server.
- Database system — Trivy DB lifecycle.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.