Infrastructure worth keeping — and kept patched.

Upgrade, back up and move a build cache server

Can you upgrade a build cache, back it up or move it to a new server without losing what it holds? We ran all three with FosterStack Cache, and this page shows what happened.

The short answer

Our advice, not a test result

The upgrade

docker pull ghcr.io/fosterstack/cache:0.2.2
docker stop fscache && docker rm fscache
docker run -d --name fscache -p 127.0.0.1:8080:8080 \
  -v fscache-data:/home/nonroot \
  ghcr.io/fosterstack/cache:0.2.2

What we saw

First, from 0.1.0 to 0.2.1 and back:

StepResult
0.1.0: store three entries on a fresh volume201 each; its metrics show 3 entries, 29 bytes
Stop 0.1.0, start 0.2.1 on the same volumestarts normally; the status page shows "version": "v0.2.1", 3 entries, 29 bytes; all three values read back
0.2.1: store two more201 each; 5 entries
Stop 0.2.1, start 0.1.0 on the same volume againstarts normally; all values read back, including the two written by 0.2.1

We then did the same from 0.2.1 to 0.2.2, the latest release, and back:

StepResult
0.2.1: store three entries on a fresh volume201 each; the status page shows 3 entries, 29 bytes
Stop 0.2.1, start 0.2.2 on the same volumestarts normally; the status page shows "version": "v0.2.2", 3 entries, 29 bytes; all three values read back
0.2.2: store two more201 each; 5 entries, 49 bytes
Stop 0.2.2, start 0.2.1 on the same volume againstarts normally; the status page shows 5 entries, 49 bytes; all five values read back

Two differences between the releases

Back up and restore a self-hosted build cache

A big cache takes days of builds to fill again, and you may want to move it to a new host. A backup is worth it only if refilling is expensive for you, or if you are moving the cache to a new server. To simply empty a cache, see how to clear or reset a build cache.

Where the data lives

The Docker command in our guides mounts a volume at /home/nonroot. The server keeps its blobs and index in a data folder inside it, and it runs as user 65532. Backing up the volume backs up the cache.

1. Stop the server, then back up the volume

We stopped the container first. The container image has no shell, so a second small container does the copying:

docker stop fscache
docker run --rm -v fscache-data:/data:ro -v "$PWD":/backup ubuntu:24.04 \
  tar czf /backup/fscache-data.tgz -C /data .

In our test, with three small entries, the archive held a data/blobs/ folder with one folder per entry prefix, and was 578 bytes.

2. Restore it into a new volume

To check it, we deleted the container and the volume, then restored into a new, empty one. We ran this on the 0.2.1 image; use the release that wrote the backup:

docker volume create fscache-data-restored
docker run --rm -v fscache-data-restored:/data -v "$PWD":/backup:ro ubuntu:24.04 \
  sh -c 'tar xzf /backup/fscache-data.tgz -C /data'
ls -ln /data   # inside the helper: the files are owned by 65532

Listing the restored volume showed the data folder still owned by user and group 65532, which is what the server runs as. If you restore as a different user, the server will not be able to write.

3. Start the server on the restored volume

docker run -d --name fscache -p 127.0.0.1:8080:8080 \
  -v fscache-data-restored:/home/nonroot ghcr.io/fosterstack/cache:0.2.1

The status page and the entries were all back:

$ curl -s localhost:8080/statusz | grep -E '"store_entries"|"store_bytes"'
  "store_bytes": 32,
  "store_entries": 3,
$ curl -s localhost:8080/alpha
value-alpha
$ curl -s -o /dev/null -w '%{http_code}\n' localhost:8080/nothere
404

Move a Maven build cache to a new server

You are replacing the machine that runs your build cache and your builds use the Apache Maven Build Cache Extension. Here is what to change, what to expect from the first build, and how to keep the cache warm.

What we saw

BuildServer it usedResult
1Old server, emptyBuilt the project and saved the result to the server
2Old server, from another machineRestored from the cache, no compile
3New server, empty, only the address changedFull build, saved to the new server
4New server, from another machineRestored from the cache, no compile
5New server started on a copy of the old data folderRestored from the cache, no compile

Option 1: change the address only

Start the new server, then edit the url in the cache config and commit it. We changed this one line and nothing else:

<remote enabled="true" saveToRemote="true" id="fosterstack-cache">
  <url>http://127.0.0.1:18151/</url>
</remote>

Build 3 had no cached result to find, so Maven compiled the project and saved it:

[INFO] Attempting to restore project demo:demo from build cache
[INFO] Compiling 1 source file with javac [debug release 17] to target/classes
[INFO] Saved to remote cache http://127.0.0.1:18151//v1.1/demo/demo/ebb9bceba2f7a6bc/demo.jar

From then on, every other machine pointing at the new address gets the result from the new server, as build 4 did. Anyone who still has the old address in their config keeps using the old server until they update.

Option 2: copy the data folder first

This keeps the new server warm from the first build. Stop the old server, copy its data folder, and start the new server with its data folder set to the copy. See back up and restore for why the old server should be stopped first.

cp -R data-old data-new-copied
FSCACHE_ADDR=127.0.0.1:18152 FSCACHE_DATA_DIR=$PWD/data-new-copied fscache

Build 5 found the result straight away, with no compile:

[INFO] Attempting to restore project demo:demo from build cache
[INFO] Found cached build, restoring demo:demo from cache by checksum ebb9bceba2f7a6bc

The new server's status page agreed: 2 hits and 0 misses at that point.

How to tell it worked

Look for Found cached build, restoring in the Maven output. You may also see Saved to remote cache lines on a build that restored. In our run these were a small report file that the extension saves each time, not a rebuild. If a build prints Compiling instead of Found cached build, it did not find a stored result.

Credentials and other settings

If the new server has logins, Maven reads them from the <server> entry in settings.xml whose id matches the id on the <remote> line. See Maven remote build cache setup for that, and behind a corporate proxy if your builds go through one. To move Gradle builds too, see one server for Gradle and Maven.

How we checked

Related: how releases are built and signed and verify a release yourself, so you can check the new version before you run it.

Changelog FosterStack home