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:

  1. The container images, saved as a single tar file.
  2. 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:

git clone https://github.com/specivo/specivo.git

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

docker load -i images.tar

In the repo directory, pin the version you transferred so Compose uses your local image instead of trying to pull:

# .env
SPECIVO_VERSION=0.1.10

Then bring the stack up:

docker compose up -d

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).

  1. 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 needs curl and sha256sum or shasum). It fetches multilingual-e5-small.onnx and tokenizer.json from a pinned revision and checks their SHA-256. If the offline host itself reports cannot reach huggingface.co from python -m specivo.cli.download_model, that message lists the same files and checksums.
  2. Copy the resulting models folder to <SPECIVO_DATA_DIR>/models/ on the offline host, so that <SPECIVO_DATA_DIR>/models/multilingual-e5-small.onnx exists.
  3. Index the content you already have:

    docker compose exec api python -m specivo.cli.backfill_embeddings
    

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.