kache 1.2.0

Compiler cache for Rust, C/C++ and CUDA, with S3, GCS, shared-filesystem and OCI remotes.
---
title: Google Cloud Storage setup
description: Use a GCS bucket as the remote cache with Application Default Credentials
---

A GCS remote uses the same objects as S3, stored in a Google Cloud Storage bucket.

```toml title="~/.config/kache/config.toml"
[cache.remote]
type = "gcs"
bucket = "acme-build-cache"
prefix = "artifacts"
```

`type = "gcs"` is required. The remote takes `bucket`, `prefix` (default `artifacts`) and `endpoint`, from the config file only: the `KACHE_S3_*` overrides for bucket, endpoint, region, prefix, profile and user agent do not apply. Setting `region`, `profile`, `user_agent`, `path` or `atomic_write_dir` is an error; Kache logs why and builds without the remote.

## Credentials

Kache uses Application Default Credentials, in this order:

1. the key file named by `GOOGLE_APPLICATION_CREDENTIALS`;
2. the user credentials that `gcloud auth application-default login` wrote;
3. the VM metadata server, which covers GKE workload identity and Compute Engine.

On GitHub Actions, `google-github-actions/auth` with workload identity federation sets `GOOGLE_APPLICATION_CREDENTIALS` for the job.

Readers need `storage.objects.get`. Writers also need `storage.objects.create`, plus `storage.objects.delete` to replace the build manifests, shards and prediction rows Kache rewrites. `roles/storage.objectViewer` covers readers. `roles/storage.objectCreator` cannot replace objects, so give writers `roles/storage.objectUser`. Listing (`cache.remote_key_listing = true`, `kache sync`) also needs `storage.objects.list`.

## Behaviour

Entry packs and their manifests are written create-only (`ifGenerationMatch=0`), so an existing entry is never replaced. Build manifests, shards and prediction rows are replaced in place. Build manifests and shards merge before the write, but GCS offers no entity-tag precondition through the client Kache uses, so two jobs finishing at the same moment can still drop each other's manifest entries.

A refused read is reported as an error, not a miss.

## Emulator

`endpoint` points Kache at another server, such as a local emulator. Requests to a custom endpoint go unsigned.

```toml
[cache.remote]
type = "gcs"
bucket = "test"
endpoint = "http://127.0.0.1:4443"
```