Install a build cache on an air-gapped network
The server is one static program with nothing to download at install time and nothing it reaches out for at startup. So an air-gapped install is short: move the files across, verify them, run.
What to bring across
On a machine with internet access, download these from the release page:
- The archive for your platform, for example
fscache_X.Y.Z_linux_amd64.tar.gz. checksums.txtandchecksums.txt.bundle, which is the signature over the checksums.cosign, the signature checker. It is one static binary and will not be on a fresh isolated machine.- If you run containers: the image as a tar file, for example
crane pull ghcr.io/fosterstack/cache:X.Y.Z fscache-X.Y.Z.tar. Verify the image withcosign verifybefore you export it, while you still have registry access (the image verification guide has the command). Images are published for bothlinux/amd64andlinux/arm64. Across a gap you pick one by hand, so pull on a machine of the destination type, or add--platform.
Verify before you cross the gap
Do this on the connected side, where the signature check can reach its public log:
# 1. Prove the checksums file is ours
cosign verify-blob \
--bundle checksums.txt.bundle \
--certificate-identity-regexp='^https://github.com/fosterstack/cache/' \
--certificate-oidc-issuer='https://token.actions.githubusercontent.com' \
checksums.txt
# 2. Prove your archive matches it
sha256sum -c <(grep "fscache_X.Y.Z_linux_amd64.tar.gz" checksums.txt | grep -v sbom)
grep -v sbom drops the SBOM line, because that file is not carried across. Without it, sha256sum reports the file as missing and fails.
Both steps matter. The checksum alone only shows the archive matches a file you carried beside it. The signature is what ties that file to us.
Install on the isolated side
For the binary: unpack the archive and follow the install guide from the unpack step, including the systemd service. There is no separate offline procedure.
For containers:
docker load -i fscache-X.Y.Z.tar
docker run -d -p 127.0.0.1:8080:8080 -v fscache-data:/home/nonroot ghcr.io/fosterstack/cache:X.Y.Z
Real deployments terminate HTTPS at a proxy in front of the server, because Gradle sends the password with every request. The offline install guide has the full detail, including what to do for later upgrades.
It does not call out
The server sends no telemetry and has no update or licence check, so it behaves the same with no route to the internet.
How we checked
We followed this page on a GitHub-hosted Linux machine with FosterStack Cache 0.2.2.
- The two verify steps printed
Verified OKandfscache_0.2.2_linux_amd64.tar.gz: OK. An archive with eight extra bytes added at the end failed step 2 withfscache_0.2.2_linux_amd64.tar.gz: FAILED. - We unpacked the archive and checked that
fscacheis a statically linked program. We then ran it in a network namespace that had only a loopback interface: it started, answered/healthz, and stored and returned an entry. That is not a real air gap. We did not record network traffic, and we did not test a machine with no network at all. - For containers we used
docker pullanddocker savein place ofcrane pull. Thendocker load -iand thedocker runline above gave a server that answered/healthzon127.0.0.1:8080.
Not tested: crane pull, verifying the image with cosign verify, the systemd service, and later upgrades, and we put no HTTPS proxy in front of the server. The run and its log are public.
Related: how releases are built and signed and server sizing.