fix: give the scratch server image a /tmp for the vulnerability database

The runtime stage is FROM scratch, which has no /tmp, so vulnsched died at
startup with "temp dir: stat /tmp: no such file or directory" and no scan
ever ran. Nothing in the server wrote to a temporary directory before the
trivy-db puller, which is why this only appeared now.

scratch cannot mkdir its own, so the directory is staged in the builder at
1777 and copied in. Also corrects CLAUDE.md, which described this image as
Alpine; the time/tzdata import it justifies is if anything more load-bearing
on scratch.
This commit is contained in:
2026-08-06 15:46:30 +01:00
parent 9ba3d4a61f
commit da6d64f95c
2 changed files with 16 additions and 1 deletions
+7 -1
View File
@@ -147,7 +147,7 @@ with `"schedule"` as the actor, so there is no second dispatch path and the run
detail page needed no changes.
`main.go` imports `_ "time/tzdata"`, and it is load-bearing: `server/Dockerfile`
builds on Alpine, which ships no zone database, so without it
runs on `scratch`, which ships no zone database, so without it
`time.LoadLocation("Europe/London")` fails and every schedule silently falls
back to UTC — an hour wrong for half the year, in the direction nobody notices
until a maintenance window lands in business hours. It works on a developer
@@ -350,6 +350,12 @@ is where risk goes to be forgotten. An unsupported distribution reports
unknown is the same lie as a silently stale database, which is why
`vulndb_meta.pulled_at` is on screen rather than only in a log.
**`server/Dockerfile`'s runtime stage is `scratch`, so it carries an explicitly
copied `/tmp`.** The scheduler unpacks the database to a temporary directory,
and a scratch image has none — the failure is `vulnsched: temp dir: stat /tmp:
no such file or directory`, logged once at boot while every other subsystem
runs normally, so the only symptom is a fleet that never reports a finding.
Two environment variables: `VANTAGE_TRIVY_DB_REF` mirrors the artifact for
air-gapped installs, and `VANTAGE_VULNDB_DISABLED` switches the puller and
scheduler off entirely.
+9
View File
@@ -18,10 +18,19 @@ ARG VERSION=dev
RUN cd server && CGO_ENABLED=0 GOOS=linux go build \
-ldflags="-s -w -X main.Version=${VERSION}" -o /vantage-server ./cmd
# Staged so the scratch image below can have a /tmp. It cannot mkdir one
# itself — scratch has no shell — and os.MkdirTemp fails outright without it.
RUN mkdir -p /staging/tmp && chmod 1777 /staging/tmp
# Runtime stage
FROM scratch
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
# vulndb unpacks the ~50MB trivy-db here. Without it the scheduler stops at
# "temp dir: stat /tmp: no such file or directory" and no scanning happens,
# while everything else in the process runs perfectly well.
COPY --from=builder /staging/tmp /tmp
COPY --from=builder /vantage-server /vantage-server
COPY default_steps/ /opt/default-steps/