Air-gapped install¶
You can run Specivo on a host with no outbound internet. The idea is simple: do the downloading on a connected machine, carry everything across, and load it on the offline host. At runtime Specivo needs no internet at all.
What you need to transfer¶
Two things move from the connected machine to the offline host:
- The container images, saved as a single tar file.
- The cloned repo, which contains
docker-compose.yml, the nginx config, and.env.example.
1. On a connected machine — pull and save the images¶
Pull the four images Specivo uses. Pin specivo/specivo to the release you intend to run instead of
latest, so the offline host gets a known version.
TAG=0.1.10 # the Specivo release you want
docker pull specivo/specivo:$TAG # or ghcr.io/specivo/specivo:$TAG, the same image
docker pull pgvector/pgvector:pg18
docker pull redis:7-alpine
docker pull nginx:1-alpine
Save them all into one archive:
docker save \
specivo/specivo:$TAG \
pgvector/pgvector:pg18 \
redis:7-alpine \
nginx:1-alpine \
-o images.tar
Also clone the repo so you have the compose file and nginx config to carry over:
2. Transfer to the offline host¶
Copy both images.tar and the cloned specivo/ directory to the offline host by whatever means you
use to cross the air gap (removable media, an internal file share, and so on).
3. On the offline host — load and start¶
In the repo directory, pin the version you transferred so Compose uses your local image instead of trying to pull:
Then bring the stack up:
Create the first admin user and sign in exactly as on a normal install:
docker compose exec api python -m specivo.cli.admin create \
--login admin --email [email protected] --password 'choose-a-strong-one'
Open http://your-specivo-host:9933 and sign in.
Migrations still run automatically
The entrypoint applies migrations and seeds defaults from inside the loaded image. There is nothing to download for this step.
Semantic search offline¶
The embedding model is not in the Docker image or the release bundle; it is a separate download of
about 487 MB from Hugging Face. To use semantic search on an air-gapped host, fetch it on the
connected machine and copy it into SPECIVO_DATA_DIR on the offline host (default ./specivo-data).
- On the connected machine, download the model with
bash scripts/download-model.sh ./models(the script is in the repository and in the release bundle; it needscurlandsha256sumorshasum). It fetchesmultilingual-e5-small.onnxandtokenizer.jsonfrom a pinned revision and checks their SHA-256. If the offline host itself reports cannot reach huggingface.co frompython -m specivo.cli.download_model, that message lists the same files and checksums. - Copy the resulting
modelsfolder to<SPECIVO_DATA_DIR>/models/on the offline host, so that<SPECIVO_DATA_DIR>/models/multilingual-e5-small.onnxexists. -
Index the content you already have:
Specivo looks for the files whenever it needs them, so no restart is needed. It loads them locally and runs the model on CPU, with no external calls.
Without the model, keyword search and the rest of Specivo work normally; only meaning-based search is unavailable.
No runtime internet required
Once the images are loaded and the optional model is in place, Specivo needs no outbound internet. The only time you go online again is to fetch a newer image for an upgrade — repeat the pull/save/transfer/load cycle with the new tag.
Exchange rates offline¶
Money reports convert amounts with daily exchange rates. The optional daily fetch of the ECB rates
is off by default, so an offline host makes no request for them. Enter rates by hand or import a
date,base,quote,rate CSV file carried across with your other transfers; see
Exchange rates.
AI model prices offline¶
The AI model prices that value AI usage ship inside the image, as of the release date, and are loaded without any download. Enter newer or missing prices by hand; see AI model prices.