Testing a backup
You do not know a backup works until someone has restored it. Testing it does not touch your
instance, but it cannot be a second docker compose up either: the compose file pins its project
name, so a second run recreates the stack you are running instead of starting a copy beside it. Build the image under a name of your own and run the pair by hand.
Running a copy beside your instance
Section titled “Running a copy beside your instance”-
A network and a database of their own.
Terminal window docker network create badlen-restore-testdocker run -d --name badlen-restore-db --network badlen-restore-test \-e POSTGRES_USER=rt -e POSTGRES_PASSWORD=rt -e POSTGRES_DB=rt \-v badlen-restore-test-pgdata:/var/lib/postgresql postgres:18-alpine -
The application, on a port nothing else uses. It applies the migrations itself before it serves, so there is no separate schema step. Run by hand, it expects the address in
WEB_ORIGIN, the name the compose file givesPUBLIC_URL.Terminal window docker build -t badlen-restore-test -f Dockerfile.api --target runtime .docker run -d --name badlen-restore-app --network badlen-restore-test -p 8099:3001 \-e DATABASE_URL='postgresql://rt:rt@badlen-restore-db:5432/rt?schema=public' \-e JWT_ACCESS_SECRET="$(openssl rand -hex 32)" \-e SECRET_ENCRYPTION_KEY="$(openssl rand -base64 32)" \-e WEB_ORIGIN=http://localhost:8099 \badlen-restore-test -
Open
http://localhost:8099, sign up with anything, import your file. -
Take it all down. Nothing here should outlive the drill, the image included: it is a copy of your instance close to 800 MB, and it is the piece most easily forgotten, because it is not listed with the containers.
Terminal window docker rm -f badlen-restore-app badlen-restore-dbdocker volume rm badlen-restore-test-pgdatadocker network rm badlen-restore-testdocker rmi badlen-restore-test
The two secrets on that run
Section titled “The two secrets on that run”Both secrets on that docker run are generated rather than typed, and the access one especially:
the boot check refuses a JWT_ACCESS_SECRET shorter than 16 characters, and a container it refuses
exits at once, after applying the migrations. Nothing then listens on 8099, so the page you open
gets no answer, and the refusal shows only in docker logs badlen-restore-app, where it names the
variable.
The encryption key on the line under it is a new one every time, because that is what the drill tests: a sealed file opens here, on an instance that has never seen the key of the one that wrote it.
Net worth, operations and cost basis
Section titled “Net worth, operations and cost basis”Compare against the real instance: the net worth, the number of operations on your busiest account, and one line’s cost basis. Those three are enough to catch an incomplete restore.