No description
  • Go 86.9%
  • Nix 9.8%
  • Bluespec 1.2%
  • HTML 1%
  • PLpgSQL 0.6%
  • Other 0.5%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Philip Taron c121c5fcce client: do not skip cached closures when verifying S3 integrity
--verify-s3-integrity exists to find objects the database wrongly
believes present. The present shortcut skipped fully cached closures
before the server saw them, and the server can only verify the objects
a pending closure names, so those closures were never verified.

(cherry picked from commit dbcd3ba153)

Change-Id: Icbae1be217e3ccf8af94b1a83ddc1ecbf7e113a3
2026-10-25 20:37:58 +01:00
.github release: attest the goreleaser archives 2026-10-06 13:12:28 +02:00
api server, client: report a GC run that another replica is executing 2026-10-05 13:18:25 +02:00
bin release: share one version between nix and helm 2026-10-06 12:45:44 +02:00
client client: do not skip cached closures when verifying S3 integrity 2026-10-25 20:37:58 +01:00
cmd push --stdin: tell when the size limit skipped a path 2026-10-08 12:52:26 +00:00
cmdutil cmd: extract shared subcommand setup into cmdutil 2026-07-08 21:12:03 +02:00
deploy/helm/niks3 bump version 1.15.0 2026-10-08 17:06:53 +00:00
hook Merge fb7ceed829 into gitea-mq/batch/507970 2026-10-25 19:07:16 +00:00
nix Merge 0e7f1253fa into gitea-mq/batch/507967 2026-10-25 17:17:25 +00:00
ratelimit client: add adaptive rate limiting for S3 and server requests 2026-02-06 13:15:59 +01:00
server client: do not skip cached closures when verifying S3 integrity 2026-10-25 20:37:58 +01:00
spec spec: insert pending rows before the lookup, recheck in the sweep 2026-10-01 10:02:05 +02:00
.envrc replace minio with rustfs 2025-12-09 23:13:48 +01:00
.gitignore chore(gitignore): adopt the official Nix template 2026-06-28 10:48:41 +02:00
.golangci.yml golangci: disable deprecated gomodguard 2026-09-21 11:26:27 -07:00
.goreleaser.yaml goreleaser: mark tags with prerelease suffix as prerelease 2026-08-28 09:41:20 +02:00
.mergify.yml add mergify 2024-10-27 14:28:58 +01:00
.sqlfluff sqlfluff: disable for query.sql 2025-08-31 21:31:58 +02:00
CONTRIBUTING.md docs: replace stale process-compose dev setup with test-driven workflow 2026-07-09 09:54:29 +02:00
flake.lock flake.lock: update nixpkgs 2026-10-25 18:14:41 +01:00
flake.nix deploy: add a Grafana dashboard 2026-09-23 15:25:44 +02:00
go.mod build(deps): bump the gomod group with 3 updates 2026-10-25 18:14:30 +01:00
go.sum build(deps): bump the gomod group with 3 updates 2026-10-25 18:14:30 +01:00
LICENSE add MIT license 2025-11-06 13:26:13 +01:00
README.md deploy: add a Grafana dashboard 2026-09-23 15:25:44 +02:00
sqlc.yml sqlc: fix schema path 2024-12-09 11:02:02 +01:00
VERSION bump version 1.15.0 2026-10-08 17:06:53 +00:00

niks3 logo

S3-backed Nix binary cache with garbage collection

The idea is to have all reads be handled by the s3 cache (which itself can be high-available) and have a gc server that tracks all uploads to the cache and runs periodic garbage collection on s3 cache. Since writes to a binary cache are often not as critical as reads, we can vastly simplify the operational complexity of the GC server, i.e. only running one instance next to the CI infrastructure.

Architecture

Write path

flowchart LR
    niks3cli[niks3 CLI] -->|request upload| niks3[niks3 Server]
    niks3 -->|presigned S3 URLs| niks3cli
    niks3cli -->|PUT NAR + narinfo| s3[(S3 Bucket)]
    niks3 -->|track references| db[(PostgreSQL)]

The niks3 CLI requests an upload from the server, which returns pre-signed S3 URLs. The client uploads NAR files and narinfo directly to S3. The server tracks references in PostgreSQL for garbage collection.

Read path

flowchart LR
    nix[Nix Client] -->|read NAR + narinfo| s3[(S3 Bucket)]

Nix clients read directly from S3 (or a CDN in front of it) without going through niks3. This allows the read path to scale independently and remain highly available.

Read proxy (optional)

flowchart LR
    nix[Nix Client] -->|read request| niks3[niks3 Server]
    niks3 -->|fetch on behalf| s3[(S3 Bucket)]

For private S3 buckets, niks3 can proxy read requests from Nix clients to S3 using its own credentials. Enable with --enable-read-proxy. See the Private S3 Buckets wiki page.

With --read-redirect-ttl 15m NAR requests are answered with a 307 to a presigned S3 URL instead of being streamed, so NAR bytes bypass niks3. Narinfos and other metadata stay proxied. Note that anyone holding such a URL can fetch that object until it expires, regardless of read-proxy authentication.

Features

Binary Cache Protocol Support

niks3 implements the Nix binary cache specification with the following features:

  • Cryptographic signing: NAR signatures using Ed25519 keys (compatible with nix key generate-secret)
  • NAR files (nar/): Compressed with zstd, stored in S3
  • Narinfo files (.narinfo): Metadata with cryptographic signatures
    • StorePath, URL, Compression, NarHash, NarSize
    • References, Deriver
    • Signatures (Sig fields)
    • CA field for content-addressed derivations
  • Build logs (log/): Compressed build output storage
  • Realisation files (realisations/*.doi): For content-addressed derivations
  • Cache info (nix-cache-info): Automatic generation with WantMassQuery, Priority

Advanced Features

  • Multipart uploads: Efficient handling of large NARs (>100MB)
  • Transactional uploads: Atomic closure uploads with rollback on failure
  • Garbage collection: Reference-tracking GC with configurable retention
  • Parallel uploads: Client parallelizes NAR and metadata uploads
  • Streaming push: niks3 push --stdin for long-running producers

Operational Features

  • Authentication via API tokens (Bearer auth)
  • OIDC authentication for CI/CD systems (GitHub Actions, GitLab CI)
  • S3 credentials via static keys (--s3-access-key / --s3-secret-key) or IAM (--s3-use-iam for IRSA, EC2 instance profiles, ECS task roles)
  • Automatic upload via post-build-hook with crash-safe SQLite queue

Choosing an S3 Provider

niks3 works with any S3-compatible storage provider. We recommend Cloudflare R2 for most users due to zero egress fees and excellent performance.

For detailed pricing comparison and alternative providers, see the S3 Provider Comparison wiki page.

Setup

For complete setup instructions, see the Setup Guide in the wiki.

Kubernetes

Chart: oci://ghcr.io/mic92/charts/niks3 (source in deploy/helm/niks3), image: ghcr.io/mic92/niks3. See the Kubernetes wiki page for Postgres/S3 wiring and letting pods push via their service account token.

Monitoring

Prometheus metrics on /metrics and a Grafana dashboard (deploy/helm/niks3/files/niks3.json, flake output dashboards.niks3). See the Monitoring wiki page.

OIDC Authentication (CI/CD)

niks3 supports OIDC authentication for CI/CD systems. See the wiki for details:

Development

For development setup, database migrations, benchmarks, and contribution guidelines, see CONTRIBUTING.md.

Real-World Deployments

Need commercial support or customization?

For commercial support, please contact Mic92 at [email protected] or reach out to Numtide.