Installing with no Internet access¶
Some sites have no route out, by policy or by construction — an industrial network, a hosting environment under accreditation, a customer who will not open outbound HTTPS from the administration segment. The platform installs there without exception, and this document goes from the archive to the first screen.
Nothing in the product phones home. The licence is a signed token read locally against a public key compiled into the image; there is no licence server, no telemetry, and no check that needs a route out. Once the images are on the machine, the platform runs indefinitely without ever reaching anything outside the site.
What you fetch, on a machine that does have access¶
From the release page, the offline bundle and the fingerprint file:
| File | What it holds |
|---|---|
infrareplica-hors-ligne-<version>.tar.gz |
the four images, the Compose file, env.example, first-deployment.sh, README.md |
SHA256SUMS |
the fingerprints of everything published with that release |
Check what you received before carrying it across:
Every line must answer OK. This is the only verification the isolated site can
do on its own: the fingerprints are published beside the archive, and once you
are inside there is nothing left to compare against.
The archive is a few hundred megabytes. Carry it in on whatever your site allows — a removable drive, a one-way file transfer, a controlled repository.
On the isolated machine¶
mkdir infrareplica && cd infrareplica
tar -xzf ../infrareplica-hors-ligne-<version>.tar.gz
docker load -i infrareplica-images.tar
docker load restores four images: the platform, the agent, PostgreSQL and
MinIO. Nothing else is pulled, and nothing will be.
The Compose file of the offline bundle names its images by tag and not by
digest, unlike the one published for connected sites. That is deliberate:
docker load does not restore registry digests, so a digest-pinned file would
send Docker looking for images that are already sitting on the machine. What
guarantees what you received is the sha256 of the archive, which you checked
above.
Configuration¶
sh first-deployment.sh --hostname backup.internal.example \
--tls selfsigned --org "Your organisation"
The script writes .env, generates every secret that can be generated, and
restricts the file to its owner. Then open it and paste the one value it cannot
produce:
A licence is negotiated and signed by the supplier; nothing on this machine can mint one, which is why it is the one value the script leaves empty. The platform refuses to start without it: there is no honest default for a negotiated period of use, and a platform that invented one would grant a service nobody agreed to.
A token that is present but unreadable — truncated, quoted twice, wrapped across two lines — does not prevent start-up. The platform comes up, refuses every new backup, keeps everything readable, downloadable and restorable, and says so in the logs and in a banner. Turning a typo into a fleet that can no longer even be reached through the interface would be the worse fault.
TLS, and why automatic certificates are not an option here¶
An isolated site cannot obtain a certificate from a public authority: the
validation is performed from the Internet, against a publicly resolvable
name. --tls own is therefore the right answer if you have an internal
authority, which most such sites do — browsers already trust it, and nobody has
to import anything.
Failing that, --tls selfsigned encrypts just as well; what it cannot do is
prove who you are. Import tls/cert.pem into the trust store of the machines
that will sign in, otherwise the warning becomes a habit — a poor one on a
platform that holds device credentials.
Serving in clear is possible and sometimes argued for on a closed network. It sends the session token unencrypted: whoever listens on the segment replays it and becomes an administrator of the platform. The platform says so in its logs at every start.
Several names, which an isolated site nearly always has¶
An administration network reaches the same machine under a short name, a fully qualified one, and often a fixed address. A browser arriving by a name that is not in the certificate refuses the connection, and the message does not say which name it expected — you are left comparing what you typed with what you configured.
List them all:
sh first-deployment.sh --hostname backup.internal.example \
--tls selfsigned --org "Your organisation" \
--san backup,infrareplica.lan,10.0.0.12
Addresses are recognised as such and written as addresses; --hostname,
localhost and 127.0.0.1 are always included, so a check from the machine
itself works while you are still deploying.
Adding a name later does not mean going through the whole first deployment again. The guard that protects the secrets stays closed; only the certificate is touched:
sh first-deployment.sh --hostname backup.internal.example --tls selfsigned \
--san backup,10.0.0.12,a-new-one.lan --replace-cert
docker compose --profile tls restart caddy
The restart is not optional: the proxy does not watch these files and keeps serving the previous certificate until it is restarted. And with a self-signed certificate, the machines that imported the old one must import the new — the old no longer matches what is presented.
A certificate already in place is never replaced without --replace-cert,
whether it came from your own authority or from openssl.
Starting¶
The init service runs once and by itself — schema, per-customer isolation,
application role, then the bucket with versioning and object lock. It must end
in exited (0); anything else means the platform will not come up behind it.
Create the first account. There is no default account, deliberately:
At least twelve characters, and quote it — a password passed unquoted is
rewritten by the shell, so what gets hashed is not what you typed, and the
sign-in page then answers invalid credentials with nothing to explain it. If
that happens, set a new one on the existing account with --replace-password
rather than starting over.
Reaching the interface¶
Open https://backup.internal.example — the name you gave to --hostname, the
one the certificate was issued for. An address that is not in the certificate is
refused by the browser, and the message does not say which name it expected.
Two endpoints answer without signing in, and they do not say the same thing:
curl -sk https://backup.internal.example/health # {"status":"ok","version":"..."}
curl -sk https://backup.internal.example/ready # {"status":"ok","rls_tables":...}
/health only says the process answers. /ready is the one that matters: it
refuses to declare the platform ready if a table that should be under an
isolation policy is not. A /ready failing on that ground means one customer's
data could be visible from another customer's account — do not put such an
instance into service.
Agents on an isolated site¶
The agent image came in the same archive, so nothing has to be fetched. Enrolment works as it does anywhere else, described in Agents: the agent opens an outbound connection towards the platform, on the site's own network. No inbound flow, and no route out of the site.
What an isolated site does need is for the agent to reach the platform under a
name carried by the control-plane certificate — BKP_GRPC_SERVER_NAMES. An
agent reaching it under a name absent from that list fails TLS verification, and
that is the commonest cause of an enrolment that never completes.
Upgrading¶
The same way, with the archive of the new version:
docker load -i infrareplica-images.tar
cp docker-compose.yaml /path/to/infrareplica/
cd /path/to/infrareplica && docker compose --profile tls up -d
Your .env is not touched, and neither are the volumes. The platform and the
agents are published together under the same number; the release notes give the
window during which an older agent still works against a newer platform, which
is what lets you upgrade the platform first and the agents afterwards.
Keep the previous archive until the new version has run for a few days. It is the only way back on a site that cannot fetch anything.