Migrate from Build Cache Node: Gradle and Maven setup
+
Stand up a replacement cache, change one URL, check that it works. About 30 minutes for Gradle. There is no data to move.
+
+
Before you start
+
A build cache holds copies of things your builds can always rebuild, so there is nothing to export from the old node. Your first build on the new server just fills it. If you have not read why the node is going away, see Build Cache Node end of life.
+
+
Step 1: Run the new cache server
+
docker run -d -p 8080:8080 -v fscache-data:/home/nonroot ghcr.io/fosterstack/cache:latest
+
For anything beyond a first look, pin a specific version instead of latest. Put the server behind HTTPS before real builds use it. Other ways to run it (bare binary with systemd, Kubernetes, offline networks) are in the install guide.
+
If the server can be reached by anyone you do not trust, turn on Basic Auth. Anyone who can write to the cache can change what your later builds use.
+
+
Step 2: Gradle build cache setup
+
Turn the cache on, in gradle.properties:
+
org.gradle.caching=true
+
Then point Gradle at the new server in settings.gradle.kts. If you used the old node, you only change the URL:
Keep the comment lines: a cache block that points at an unfamiliar host looks like data theft to a reviewer without them. Keep the trailing slash on the URL. Leave the credentials block in even if the server has no password yet; it is ignored then.
+
+
Step 3: Maven build cache setup
+
Maven uses Apache's Build Cache Extension. FosterStack Cache implements the server side of it. The server part is built; its acceptance testing is still in progress.
+
Add the extension in .mvn/extensions.xml (check Maven Central for the current version):
If the server uses Basic Auth, add a matching <server> with the same id (fosterstack-cache) in ~/.m2/settings.xml. Then run mvn install.
+
The extension itself is Apache's project. If your hit rate looks low, start with the extension's own configuration guide.
+
+
Step 4: Check that it works
+
For Gradle, run the build twice:
+
./gradlew build --build-cache
+
On the second run, look for FROM-CACHE next to tasks. Gradle also has a local cache that gives hits even when the remote is broken, so to test the remote itself, clear the local one and run with -i:
For Maven, build twice from a clean checkout and look for cache hits in the log for unchanged modules.
+
+
Step 5: Retire the old node
+
Once builds hit the new server, stop the old Build Cache Node container.
+
+
What you give up
+
The old node had a small web page with a purge button. FosterStack Cache has no settings page. You set it with flags and environment variables, and a read-only status page shows size and hit counts. To empty the cache, remove its volume and start again.
A build cache holds copies of things your builds can always rebuild, so there is nothing to export from the old node. Your first build on the new server just fills it. If you have not read why the node is going away, see Build Cache Node end of life.
Step 1: Run the new cache server
-
docker run -d -p 8080:8080 -v fscache-data:/home/nonroot ghcr.io/fosterstack/cache:latest
-
For anything beyond a first look, pin a specific version instead of latest. Put the server behind HTTPS before real builds use it. Other ways to run it (bare binary with systemd, Kubernetes, offline networks) are in the install guide.
+
docker run -d -p 127.0.0.1:8080:8080 -v fscache-data:/home/nonroot ghcr.io/fosterstack/cache:latest
+
For anything beyond a first look, pin a specific version instead of latest. This command listens on this machine only. For other machines to use it, put an HTTPS proxy in front. Other ways to run it: bare binary with systemd, Kubernetes, or a disconnected network.
If the server can be reached by anyone you do not trust, turn on Basic Auth. Anyone who can write to the cache can change what your later builds use.
Keep the comment lines: a cache block that points at an unfamiliar host looks like data theft to a reviewer without them. Keep the trailing slash on the URL. Leave the credentials block in even if the server has no password yet; it is ignored then.
Step 3: Maven build cache setup
-
Maven uses Apache's Build Cache Extension. FosterStack Cache implements the server side of it. The server part is built; its acceptance testing is still in progress.
+
Maven uses Apache's Build Cache Extension. FosterStack Cache implements the server side of it.
Add the extension in .mvn/extensions.xml (check Maven Central for the current version):
Once builds hit the new server, stop the old Build Cache Node container.
+
Security is the difference
+
Security is what sets this product apart. Everything below ships in the current release, and you can check each item yourself.
+
+
Signed releases. Images and the checksums file are signed with Sigstore, with no signing key stored anywhere. How to verify.
+
Build provenance. Every image and binary archive carries a signed statement naming the CI run that built it.
+
A bill of materials. Every binary archive ships with an SBOM.
+
Published vulnerability statements. A VEX file with each release says which known vulnerabilities do and do not affect it.
+
Scanned before release. Two independent scanners with different databases check every release candidate, and any finding blocks the release unless a published VEX statement explains it. RELEASING.md.
+
Rescanned every day. Every published image is scanned again daily, so a new vulnerability in something we shipped raises an issue.
+
Reproducible. Each image is assembled a second time on a separate machine, and the digests must match or the release fails.
+
Tiny and quiet. A distroless image with one static program and no shell. It sends no telemetry and makes no outbound connections.
+
A FIPS build. A FIPS variant uses Go's validated FIPS 140-3 cryptographic module.
+
Patched for everyone. We aim to ship dependency fixes within 48 hours of disclosure. That is a target, not a promise. Security patches are never withheld from the free tier.
The old node had a small web page with a purge button. FosterStack Cache has no settings page. You set it with flags and environment variables, and a read-only status page shows size and hit counts. To empty the cache, remove its volume and start again.
From ae77288509754ba6c7787780ca2937ea377f35b1 Mon Sep 17 00:00:00 2001
From: FosterStack Admin <317177128+fosterstack-admin@users.noreply.github.com>
Date: Thu, 8 Oct 2026 20:39:16 -0400
Subject: [PATCH 5/7] Security section: Signed and verifiable / Supply chain
groups, v0.2.1 facts only
---
migrate-build-cache-node/index.html | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/migrate-build-cache-node/index.html b/migrate-build-cache-node/index.html
index 19e4475..2d169b5 100644
--- a/migrate-build-cache-node/index.html
+++ b/migrate-build-cache-node/index.html
@@ -161,14 +161,23 @@
Step 5: Retire the old node
Security is the difference
Security is what sets this product apart. Everything below ships in the current release, and you can check each item yourself.
+
Signed and verifiable
Signed releases. Images and the checksums file are signed with Sigstore, with no signing key stored anywhere. How to verify.
Build provenance. Every image and binary archive carries a signed statement naming the CI run that built it.
A bill of materials. Every binary archive ships with an SBOM.
Published vulnerability statements. A VEX file with each release says which known vulnerabilities do and do not affect it.
+
Reproducible. Each image is assembled a second time on a separate machine, and the digests must match or the release fails.
+
+
Supply chain
+
+
Pinned build steps. Every GitHub Action our releases use is pinned to an exact commit, and the container base image is pinned by digest.
+
Watched for updates. Dependabot watches our Actions, Go modules and the base image.
Scanned before release. Two independent scanners with different databases check every release candidate, and any finding blocks the release unless a published VEX statement explains it. RELEASING.md.
Rescanned every day. Every published image is scanned again daily, so a new vulnerability in something we shipped raises an issue.
-
Reproducible. Each image is assembled a second time on a separate machine, and the digests must match or the release fails.
+
+
Small, quiet and patched
+
Tiny and quiet. A distroless image with one static program and no shell. It sends no telemetry and makes no outbound connections.
A FIPS build. A FIPS variant uses Go's validated FIPS 140-3 cryptographic module.
Patched for everyone. We aim to ship dependency fixes within 48 hours of disclosure. That is a target, not a promise. Security patches are never withheld from the free tier.
Once builds hit the new server, stop the old Build Cache Node container.
Security is the difference
-
Security is what sets this product apart. Everything below ships in the current release, and you can check each item yourself.
+
Security is what sets this product apart. The release items below ship in the current release. The supply-chain items describe how we work today, in our own build and CI. You can check each one yourself.
Signed and verifiable
Signed releases. Images and the checksums file are signed with Sigstore, with no signing key stored anywhere. How to verify.
@@ -171,8 +171,10 @@
Signed and verifiable
Supply chain
-
Pinned build steps. Every GitHub Action our releases use is pinned to an exact commit, and the container base image is pinned by digest.
-
Watched for updates. Dependabot watches our Actions, Go modules and the base image.
+
Pinned build steps. Every GitHub Action our releases use is pinned to an exact commit, and a check in CI enforces it on every change. The container base image is pinned by digest.
+
Hash-checked installs. Python tooling in our CI is installed with hash checking, so a swapped package is refused.
+
A 7-day wait. Our CI holds new dependency versions for 7 days before adopting them, and Dependabot has the same cooling-off period.
+
A daily supply-chain check. Once a day, everything our build and CI pull in (actions, tools, packages) is checked against public advisory databases and malicious-package reports. Any hit opens an issue.
Scanned before release. Two independent scanners with different databases check every release candidate, and any finding blocks the release unless a published VEX statement explains it. RELEASING.md.
Rescanned every day. Every published image is scanned again daily, so a new vulnerability in something we shipped raises an issue.
If the server uses Basic Auth, add a matching <server> with the same id (fosterstack-cache) in ~/.m2/settings.xml. Then run mvn install.
+
The remote element must be inside configuration, and saveToRemote="true" is what makes the machine upload; without it the server stays empty. If the server uses Basic Auth, add a matching <server> with the same id (fosterstack-cache) in ~/.m2/settings.xml. Then run mvn install.
The extension itself is Apache's project. If your hit rate looks low, start with the extension's own configuration guide.